summaryrefslogtreecommitdiffstats
path: root/AAL
diff options
context:
space:
mode:
authorxiaomuwuye <renrongwei@chinamobile.com>2018-10-26 15:04:09 +0800
committerxiaomuwuye <renrongwei@chinamobile.com>2018-10-26 15:04:09 +0800
commitfc1b7908a77b5cce763f92b3d314057345f3ab7a (patch)
tree3154efdad680464e683d770b0c2fc17dc70834b0 /AAL
parent30fdbc9150d5f3ffdc633ae581baeb44acaea256 (diff)
upload AAL seed code
Change-Id: I96142622365ad964607b75c974011b85513e7d0f Signed-off-by: xiaomuwuye <renrongwei@chinamobile.com>
Diffstat (limited to 'AAL')
-rw-r--r--AAL/SR-IOV/README0
-rw-r--r--AAL/qat/Makefile73
-rw-r--r--AAL/qat/libcrypto.c864
-rw-r--r--AAL/qat/libcrypto.h288
-rw-r--r--AAL/qat/libcrypto_test.c1015
-rw-r--r--AAL/qat/main.c763
-rw-r--r--AAL/qat/pdcp.c660
7 files changed, 3663 insertions, 0 deletions
diff --git a/AAL/SR-IOV/README b/AAL/SR-IOV/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AAL/SR-IOV/README
diff --git a/AAL/qat/Makefile b/AAL/qat/Makefile
new file mode 100644
index 0000000..53016b7
--- /dev/null
+++ b/AAL/qat/Makefile
@@ -0,0 +1,73 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# 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.
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+#RTE_SDK = /home/gaocb/dpdk
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# binary name
+APP = libcrypto_test
+
+
+# all source are stored in SRCS-y
+SRCS-y := libcrypto.c
+SRCS-y += zuc.c
+SRCS-y += test3.c
+
+#CFLAGS += $(WERROR_FLAGS)
+
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_NTNIC),y)
+LDFLAGS += -lrte_pmd_ntnic
+endif
+
+# workaround for a gcc bug with noreturn attribute
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+CFLAGS_main.o += -Wno-return-type
+endif
+
+#CFLAGS += -I/root/workspace/nfv/dpdk-16.07/lib/librte_zuc
+#LDLIBS += -L$/home/gaocb/dpdk/lib/
+#LDLIBS += -lrte_crypto
+
+
+#EXTRA_CFLAGS += -O3 -g -Wfatal-errors
+EXTRA_CFLAGS += -O3 -g
+
+include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/AAL/qat/libcrypto.c b/AAL/qat/libcrypto.c
new file mode 100644
index 0000000..9962e26
--- /dev/null
+++ b/AAL/qat/libcrypto.c
@@ -0,0 +1,864 @@
+#include "libcrypto.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+
+#include <rte_eal.h>
+#include <rte_ethdev.h> // struct rte_eth_conf
+#include <rte_cycles.h> // rte_get_timer_hz()
+#include <rte_lcore.h> // rte_pktmbuf_pool_create
+#include <rte_ring.h> // fifo's
+#include <rte_errno.h>
+#include <rte_spinlock.h>
+#include <rte_cryptodev.h>
+#include <pthread.h>
+
+
+
+#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)
+#define DIGEST_BYTE_LENGTH_SHA512 (BYTE_LENGTH(512))
+
+#define DEFAULT_NUM_XFORMS (2)
+#define MAX_BURST_SIZE (32)
+
+#define RETURN_ADDR_FIFO_SIZE (8192*8)
+#define SEQUENCE_FIFO_SIZE (8192*8)
+
+
+#define IV_OFFSET (sizeof(struct rte_crypto_op) + \
+ sizeof(struct rte_crypto_sym_op))
+
+#define TEST_HEXDUMP(file, title, buf, len) rte_hexdump(file, title, buf, len)
+
+
+/* Only support EEA3 */
+#define CONSTRUCT_IV(IV, COUNT, BEARER, DIRECTION)\
+ do { \
+ IV[0] = (COUNT>>24) & 0xFF;\
+ IV[1] = (COUNT>>16) & 0xFF;\
+ IV[2] = (COUNT>>8) & 0xFF;\
+ IV[3] = COUNT & 0xFF;\
+ IV[4] = ((BEARER << 3) | ((DIRECTION&1)<<2)) & 0xFC;\
+ IV[5] = 0;\
+ IV[6] = 0;\
+ IV[7] = 0;\
+ IV[8] = IV[0];\
+ IV[9] = IV[1];\
+ IV[10] = IV[2];\
+ IV[11] = IV[3];\
+ IV[12] = IV[4];\
+ IV[13] = IV[5];\
+ IV[14] = IV[6];\
+ IV[15] = IV[7];\
+ } while(0)
+
+#define CIPHER2WOKER_FIFO_SIZE (4096*2)
+
+
+struct pkt_buffer {
+ unsigned len;
+ struct rte_mbuf *buffer[MAX_BURST_SIZE];
+ data_out_t callback_data[MAX_BURST_SIZE];
+};
+
+
+#define RA_FIFO
+typedef struct {
+ symmetric_key_t key;
+ struct rte_mbuf *mbuf;
+#ifdef RA_FIFO
+ struct rte_ring *return_addr_fifo;
+#endif
+ data_ctx_t data_ctx;
+ uint16_t index;
+ rte_spinlock_t lock;
+ algo_type_t type;
+ uint64_t rx_count;
+ uint64_t tx_count;
+ struct pkt_buffer pkt_buf;
+
+/*qat*/
+ struct rte_crypto_op *op[MAX_BURST_SIZE];
+ struct rte_mbuf *ibuf[MAX_BURST_SIZE];
+ struct rte_mbuf *obuf[MAX_BURST_SIZE];
+ //uint16_t length[MAX_PKT_BURST];
+ //data_t data_in[MAX_PKT_BURST];
+ //data_t data_out[MAX_PKT_BURST];
+ //unsigned datain_num;
+} sec_ctx_s;
+
+
+
+
+
+typedef struct
+{
+/////////////////////////////
+ struct rte_mempool *mbuf_pool;
+ 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 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;
+ sec_ctx_s *sec_ctx_array[MAX_BURST_SIZE];
+ struct pkt_buffer pkt_buf;
+ uint8_t *digest;
+ rte_spinlock_t queue_lock;
+ long enqueue_sum;
+ long dequeue_sum;
+}nectar_ctx_s;
+
+typedef struct {
+ struct rte_mempool *mbuf_pool;
+ callback_t __callback;
+ uint64_t timeout_ticks;
+ uint32_t sec_ctx_count;
+ uint8_t crypto_port;
+} crypto_ctx_s;
+
+
+typedef struct {
+ uint16_t data_original_len;
+ data_t data_out;
+ sec_ctx_s *sec_ctx;
+}cipher2worker_ctx_s;
+
+long count;
+
+#if 0
+
+#endif
+
+
+static int gbl_driver_id;
+volatile uint8_t running;
+static crypto_ctx_s* crypto_ctx = NULL;
+static nectar_ctx_s nectar_ctx = { NULL };
+static sec_ctx_s* g_sec_ctx;
+
+static struct rte_ring *sequence_fifo;
+rte_spinlock_t sequence_fifo_lock;
+
+rte_spinlock_t new_sec_ctx_lock;
+
+/*连接nt_crypto_cipher和nt_crypto_worker*/
+struct rte_ring *cipher2worker;
+
+static void print_stat(void) {
+
+}
+
+
+static void empty_inflight(void) {
+ printf ("\nWaiting on inflights !!\n");
+
+}
+
+/*同步加密接口*/
+static struct rte_crypto_op *
+process_crypto_request(uint8_t dev_id, struct rte_crypto_op *op)
+{
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ printf("Error sending packet for encryption");
+ return NULL;
+ }
+
+ op = NULL;
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
+ rte_pause();
+ //printf("xxxxxxxxxxxx op = %p\n", op);
+ return op;
+}
+
+/*异步加密接口*/
+static int process_crypto_request_async(uint8_t dev_id, struct rte_crypto_op *op)
+{
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ printf("Error sending packet for encryption\n");
+ return -1;
+ }
+
+ 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];
+
+ nectar_ctx_s * nectar_ctx_p = &nectar_ctx;
+
+ memcpy(cipher_key, key, key_len);
+
+ /* Setup Cipher Parameters */
+ nectar_ctx_p->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ nectar_ctx_p->cipher_xform.next = NULL;
+
+ nectar_ctx_p->cipher_xform.cipher.algo = algo;
+ nectar_ctx_p->cipher_xform.cipher.op = op;
+ nectar_ctx_p->cipher_xform.cipher.key.data = cipher_key;
+ nectar_ctx_p->cipher_xform.cipher.key.length = key_len;
+ nectar_ctx_p->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ nectar_ctx_p->cipher_xform.cipher.iv.length = iv_len;
+
+ /* Create Crypto session */
+ nectar_ctx_p->sess = rte_cryptodev_sym_session_create(
+ nectar_ctx_p->session_mpool);
+
+ rte_cryptodev_sym_session_init(dev_id, nectar_ctx_p->sess,
+ &nectar_ctx_p->cipher_xform, nectar_ctx_p->session_mpool);
+ TEST_ASSERT_NOT_NULL(nectar_ctx_p->sess, "Session creation failed");
+ return 0;
+}
+
+
+uint8_t session_is_create_flag = 0;
+int create_session(sec_ctx_s* sec_ctx_ptr)
+{
+ sec_ctx_s *sec_ctx = sec_ctx_ptr;
+ int retval;
+ uint8_t dev_id;
+ nectar_ctx_s * nectar_ctx_p = &nectar_ctx;
+
+ //g_sec_ctx = sec_ctx;
+
+ dev_id = nectar_ctx_p->valid_devs[0];
+
+ retval = create_wireless_algo_cipher_session(dev_id,
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+// RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ sec_ctx->key, KEY_SIZE,
+ MAXIMUM_IV_LENGTH);
+ if (retval < 0)
+ return retval;
+}
+
+static int
+create_wireless_algo_cipher_operation(sec_ctx_s *sec_ctx, const uint8_t *iv, uint8_t iv_len,
+ unsigned int cipher_len,
+ unsigned int cipher_offset,
+ int index)
+{
+ nectar_ctx_s *nectar_ctx_p = &nectar_ctx;
+ unsigned datain_num;
+ int i;
+
+ i = index;
+
+ /* Generate Crypto op data structure */
+ sec_ctx->op[i] = rte_crypto_op_alloc(nectar_ctx_p->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+
+ if(NULL == sec_ctx->op[i]) {
+ printf("sec_ctx->op[%d] alloc error\n", i);
+ return -1;
+ }
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(sec_ctx->op[i], nectar_ctx_p->sess);
+
+ struct rte_crypto_sym_op *sym_op = sec_ctx->op[i]->sym;
+ /* set crypto operation source mbuf */
+ sym_op->m_src = sec_ctx->ibuf[i];
+
+ /* iv */
+ rte_memcpy(rte_crypto_op_ctod_offset(sec_ctx->op[i], uint8_t *, IV_OFFSET),
+ iv, iv_len);
+ sym_op->cipher.data.length = cipher_len;
+ sym_op->cipher.data.offset = cipher_offset;
+
+ return 0;
+
+}
+static uint32_t
+ceil_byte_length(uint32_t num_bits)
+{
+ if (num_bits % 8)
+ return ((num_bits >> 3) + 1);
+ else
+ return (num_bits >> 3);
+}
+
+uint8_t session_is_teardown_flag = 0;
+void teardown_session()
+{
+ nectar_ctx_s * nectar_ctx_p = &nectar_ctx;
+ uint8_t dev_id = nectar_ctx_p->valid_devs[0];
+
+ /* free crypto session structure */
+ if(nectar_ctx_p->sess){
+ rte_cryptodev_sym_session_clear(dev_id,
+ nectar_ctx_p->sess);
+ rte_cryptodev_sym_session_free(nectar_ctx_p->sess);
+ nectar_ctx_p->sess = NULL;
+ }
+ session_is_teardown_flag = 1;
+}
+
+//int crypto_send_messages(sec_ctx_s *sec_ctx, struct rte_mbuf *m)
+int crypto_send_messages(sec_ctx_s *sec_ctx, void* data_out, uint16_t crypto_data_len)
+{
+ nectar_ctx_s * nectar_ctx_p = &nectar_ctx;
+ unsigned len;
+ //struct rte_mbuf **pkt_buffer;
+ int ret;
+ data_out_t *callback_data;
+ int j;
+
+ if(0 == data_out) {
+ printf("crypto_send_messages error: m is NULL.\n");
+ return -1;
+ }
+
+ len = sec_ctx->pkt_buf.len;
+ //pkt_buffer = sec_ctx->pkt_buf.buffer;
+ callback_data = sec_ctx->pkt_buf.callback_data;
+ callback_data[len].data = data_out;
+ callback_data[len].length = crypto_data_len;
+
+ //pkt_buffer[len] = m;
+ len++;
+
+ if(MAX_BURST_SIZE == len) {
+
+ ret = crypto_ctx->__callback(sec_ctx->data_ctx, callback_data, MAX_BURST_SIZE);
+ if(ret < 0) {
+ //printf("callback failed.\n");
+ }
+
+ len = 0;
+ }
+
+ sec_ctx->pkt_buf.len = len;
+}
+
+
+int nt_crypto_cipher(sec_ctx_t sec_ctx_ptr, iv_t *iv, cipher_input *crypto_input, uint16_t nb_cipher){
+ nectar_ctx_s * nectar_ctx_p = &nectar_ctx;
+
+ int retval, dev_id;
+ uint8_t *plaintext, *ciphertext;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+ cipher2worker_ctx_s *cipher2worker_data;
+ unsigned datain_num;
+ unsigned ret, ret2;
+ unsigned nb_result;
+ unsigned nb_result_sum;
+ int j;
+ struct rte_mbuf *m;
+ //struct rte_mbuf *bufs_crypto[MAX_PKT_BURST] = {0}; /////////////////
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+
+ if( unlikely(0 == running) ){ printf("Error in nt_crypto_cipher: libcrypto not running\n"); return 0; }
+ if( unlikely(NULL == sec_ctx_ptr) ){ printf("Error in nt_crypto_cipher: sec_ctx is null\n"); return 0; }
+ if( unlikely(NULL == iv) ){ printf("Error in nt_crypto_cipher: iv is null\n"); return 0; }
+ if( unlikely(0 == nb_cipher) ){ printf("Zero length - do nothing\n"); return 0; }
+
+ for(j=0; j<nb_cipher; j++) {
+ if((crypto_input[j].data_in == NULL) || (crypto_input[j].data_out == NULL) || (crypto_input[j].length == 0)) {
+ printf("data_in[%d] error\n", j);
+ printf("data_in[%d].data_in=%p\n", crypto_input[j].data_in);
+ printf("data_in[%d].data_out=%p\n", crypto_input[j].data_out);
+ printf("data_in[%d].length=%p\n", crypto_input[j].length);
+ return 0;
+ }
+ }
+
+ sec_ctx_s *sec_ctx = (sec_ctx_s*)sec_ctx_ptr;
+
+ for(j=0; j<nb_cipher; j++) {
+ sec_ctx->ibuf[j] = rte_pktmbuf_alloc(nectar_ctx_p->mbuf_pool);
+ if(NULL == sec_ctx->ibuf[j]) {
+ printf("sec_ctx->ibuf[%d] is NULL\n", j);
+ goto err1;
+ }
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(sec_ctx->ibuf[j], uint8_t *), 0,
+ rte_pktmbuf_tailroom(sec_ctx->ibuf[j]));
+ }
+
+ /* Check if device supports ZUC EEA3 */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_ZUC_EEA3;
+ dev_id = nectar_ctx_p->valid_devs[0];
+
+ if (rte_cryptodev_sym_capability_get(dev_id, &cap_idx) == NULL)
+ goto err1;
+
+ uint32_t COUNT = iv->counter;
+ uint32_t BEARER = iv->bearer & 0x1F;
+ uint32_t DIRECTION = iv->direction & 0x1;
+
+ uint8_t IV[16];
+ CONSTRUCT_IV(IV, COUNT, BEARER, DIRECTION);
+
+ //datain_num = sec_ctx->datain_num;
+
+ for(j=0; j<nb_cipher; j++) {
+ //sec_ctx->length[j] = crypto_input[j]->length;
+ //sec_ctx->data_in[j] = crypto_input[j]->data_in;
+ //sec_ctx->data_out[j] = crypto_input[j]->data_out;
+
+
+ plaintext_len = crypto_input[j].length;
+ /* 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(sec_ctx->ibuf[j], plaintext_pad_len);
+ if(NULL == plaintext) {
+
+ }
+ /*把待加密内容拷贝到新分配的mbuf里*/
+ memcpy(plaintext, crypto_input[j].data_in, plaintext_len);
+
+ /* Create ZUC operation */
+ /* use bit length of plaintext */
+ retval = create_wireless_algo_cipher_operation(sec_ctx, &IV[0],
+ MAXIMUM_IV_LENGTH, plaintext_len * 8,
+ 0, j);
+ if (retval < 0) {
+ goto err2;
+ }
+ }
+
+ /*加保护*/
+ rte_spinlock_lock(&nectar_ctx_p->queue_lock);
+ ret = rte_cryptodev_enqueue_burst(dev_id, 0, sec_ctx->op, nb_cipher);
+ ret2 = ret;
+ if (unlikely(ret2 < nb_cipher)) {
+ //printf("rte_cryptodev_enqueue_burst has %d failed\n", MAX_PKT_BURST - ret2);
+ do {
+ rte_pktmbuf_free(sec_ctx->op[ret2]->sym->m_src);
+ rte_crypto_op_free(sec_ctx->op[ret2]);
+ } while (++ret2 < nb_cipher);
+ }
+
+ for(j=0; j<ret; j++) {
+ while (rte_ring_full(cipher2worker)){
+ /* If crypto was shutdown while waiting.*/
+ if (unlikely(0 == running)){
+ rte_spinlock_unlock(&nectar_ctx_p->queue_lock);
+ return 0;
+ }
+ }
+
+ /*申请填充cipher2worker_data,并把cipher2worker_data送入队列*/
+ cipher2worker_data = malloc(sizeof(cipher2worker_ctx_s));
+ cipher2worker_data->data_original_len = crypto_input[j].length;
+ cipher2worker_data->data_out = crypto_input[j].data_out;
+ cipher2worker_data->sec_ctx = sec_ctx;
+
+ retval = rte_ring_enqueue(cipher2worker, cipher2worker_data);
+ if(retval < 0) {
+ free(cipher2worker_data);
+ rte_exit(EXIT_FAILURE, "sequence_fifo is error\n");
+ continue;
+ }
+
+ //TEST_HEXDUMP(stdout, "data_original[j]:", data_original[j], data_original_len);
+ }
+
+ nectar_ctx_p->enqueue_sum = ret;
+ rte_spinlock_unlock(&nectar_ctx_p->queue_lock);
+
+ return ret;
+
+err2:
+ for(j=0; j<nb_cipher; j++) {
+ if(NULL != sec_ctx->op[j]) {
+ rte_crypto_op_free(sec_ctx->op[j]);
+ }
+ }
+err1:
+ for(j=0; j<nb_cipher; j++) {
+ if(NULL != sec_ctx->ibuf[j]) {
+ rte_pktmbuf_free(sec_ctx->ibuf[j]);
+ sec_ctx->ibuf[j] = NULL;
+ }
+ }
+
+ rte_spinlock_unlock(&nectar_ctx_p->queue_lock);
+
+ return 0;
+}
+
+
+void nt_crypto_worker(void)
+{
+ int nb_result;
+ data_t data_out;
+ nectar_ctx_s * nectar_ctx_p = &nectar_ctx;
+ struct rte_crypto_op *op;
+ unsigned int nb_ciphertext;
+ uint8_t *ciphertext;
+ uint8_t dev_id = nectar_ctx_p->valid_devs[0];
+ cipher2worker_ctx_s *cipher2worker_data;
+ //sec_ctx_s *sec_ctx;
+ struct rte_crypto_op *ops_burst[MAX_BURST_SIZE];
+ struct rte_mbuf *tx_batch;
+ int j;
+ int retval;
+ sec_ctx_s *sec_ctx;
+ uint16_t crypto_data_len;
+
+ printf("Starting nt_crypto_worker\n");
+
+ while(likely(running)) {
+
+ /* Dequeue packets from Crypto device */
+ rte_spinlock_lock(&nectar_ctx_p->queue_lock);
+ nb_result = rte_cryptodev_dequeue_burst(dev_id, 0, ops_burst, MAX_BURST_SIZE);
+
+ /* Forward crypto'd packets */
+ for (j = 0; j < nb_result; j++) {
+ tx_batch = ops_burst[j]->sym->m_src;
+ if(0 == tx_batch) {
+ printf("nt_crypto_worker error: tx_batch is NULL.\n");
+ }
+
+ retval = rte_ring_dequeue(cipher2worker, (void **)&cipher2worker_data);
+ if(retval < 0) {
+ printf("rte_ring_dequeue is error\n");
+ }
+
+
+ crypto_data_len = cipher2worker_data->data_original_len;
+ ciphertext = cipher2worker_data->data_out;
+ sec_ctx = cipher2worker_data->sec_ctx;
+ memcpy(ciphertext, rte_pktmbuf_mtod(tx_batch, void *), crypto_data_len);
+ //TEST_HEXDUMP(stdout, "fifo_return_data[0]:", fifo_return_data[0], rte_pktmbuf_data_len(tx_batch));
+
+ rte_crypto_op_free(ops_burst[j]);
+ rte_pktmbuf_free(tx_batch);
+ free(cipher2worker_data);
+ crypto_send_messages(sec_ctx, ciphertext, crypto_data_len);
+ }
+
+ nectar_ctx_p->dequeue_sum += nb_result;
+ rte_spinlock_unlock(&nectar_ctx_p->queue_lock);
+ }
+
+ printf("nt_crypto_worker exit\n");
+
+}
+
+sec_ctx_t nt_crypto_new_security_context(algo_type_t algo_type, symmetric_key_t key, data_ctx_t data_ctx) {
+ if(NULL == crypto_ctx){
+ printf("Error: nectar libcrypto not running\n");
+ return NULL;
+ }
+
+ rte_spinlock_lock(&new_sec_ctx_lock);
+
+ if(MAX_SEC_CTX <= crypto_ctx->sec_ctx_count){
+ printf("Error reached max security context count.\n");
+ rte_spinlock_unlock(&new_sec_ctx_lock);
+ return NULL;
+ }
+
+ /*应该用不到*/
+ //int idx = 0;
+ //for (; idx < MAX_SEC_CTX; ++idx) {
+ // if( TIMEOUT_FREE == timeout[idx] ){
+ /* Reserve the idx by removing TIMEOUT_FREE. */
+ // timeout[idx] = TIMEOUT_DISABLED;
+ // break;
+ // }
+ //}
+
+ /* Create a new security context. */
+ sec_ctx_s* sec_ctx = (sec_ctx_s*)malloc(sizeof(sec_ctx_s));
+ if(NULL == sec_ctx){
+ printf("Error allocating memory for security context!\n");
+ goto fail_new_sec_ctx;
+ }
+ memset(sec_ctx, 0, sizeof(sec_ctx_s));
+ printf("sec_ctx=%p\n", sec_ctx);
+
+ //g_sec_ctx = sec_ctx;
+
+ /* Install the encryption key in the security context. */
+ memcpy(sec_ctx->key, key, KEY_SIZE);
+
+ /* Save the data_context for the new security context. */
+ sec_ctx->data_ctx = data_ctx;
+
+ /*应该用不到sec_ctx->mbuf */
+ //sec_ctx->mbuf = rte_pktmbuf_alloc(crypto_ctx->mbuf_pool);
+ //if(NULL == sec_ctx->mbuf){
+ // printf("Error allocating mbuf for security context!\n");
+ // goto fail_new_sec_ctx_free;
+ //}
+ //sec_ctx->mbuf->pkt_len = 0;
+
+ /*是否需要fifo?*/
+ char sec_ctx_name[32];
+ snprintf(sec_ctx_name, 32, "sec_ctx_return_fifo_%d", crypto_ctx->sec_ctx_count);
+ sec_ctx->return_addr_fifo = rte_ring_create(sec_ctx_name, RETURN_ADDR_FIFO_SIZE, SOCKET_ID_ANY, 0);
+ if (NULL == sec_ctx->return_addr_fifo) {
+ printf("Error in rte_ring_create!\n");
+ goto fail_new_sec_ctx;
+ }
+ crypto_ctx->sec_ctx_count++;
+
+
+ sec_ctx->type = algo_type;
+
+ if(0 == session_is_create_flag) {
+ create_session(sec_ctx);
+ session_is_create_flag = 1;
+ }
+ rte_spinlock_unlock(&new_sec_ctx_lock);
+
+ return (sec_ctx_t)sec_ctx;
+
+fail_new_sec_ctx:
+ rte_spinlock_unlock(&new_sec_ctx_lock);
+
+ return NULL;
+}
+
+/*
+
+Stop the security context:
+
+- must not be able to encrypt more data.
+
+- packets in the batch should be destroyed.
+- packets received should be ?destroyed? or ?called back?
+
+- sec_ctx mbuf must be free.
+
+- the sec_ctx_collection index must be NULLed.
+- the timeout must be disabled before return.
+
+*/
+int nt_crypto_end_security_context(sec_ctx_t sec_ctx_ptr) {
+
+ if(NULL == crypto_ctx) { printf("Error: Nectar libcrypto not running\n"); return -1; }
+ if(NULL == sec_ctx_ptr) { printf("Error: Nectar sec_ctx is null\n"); return -1; }
+
+ sec_ctx_s* sec_ctx = (sec_ctx_s*)sec_ctx_ptr;
+
+ rte_ring_free(sec_ctx->return_addr_fifo);
+
+ free(sec_ctx_ptr);
+
+ if(0 == session_is_teardown_flag)
+ teardown_session();
+
+ return -1;
+}
+
+static int initialize_cryptodevs(unsigned int core)
+{
+// TODO:
+ unsigned int session_size;
+ nectar_ctx_s * nectar_ctx_p = &nectar_ctx;
+
+ struct rte_cryptodev_info info;
+ uint32_t i = 0, nb_devs, dev_id;
+ uint16_t qp_id;
+ int retval;
+ struct rte_mbuf* buf;
+
+ memset(nectar_ctx_p, 0, sizeof(*nectar_ctx_p));
+
+ nectar_ctx_p->mbuf_pool = rte_mempool_lookup("CRYPTO_MBUFPOOL");
+ if (nectar_ctx_p->mbuf_pool == NULL) {
+ /* Not already created so create */
+ nectar_ctx_p->mbuf_pool = rte_pktmbuf_pool_create(
+ "CRYPTO_MBUFPOOL",
+ NUM_MBUFS, MBUF_CACHE_SIZE, 0, MBUF_SIZE,
+ rte_socket_id());
+ if (nectar_ctx_p->mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Nectar:Can't create CRYPTO_MBUFPOOL\n");
+ return -1;
+ }
+ }
+
+ nectar_ctx_p->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 (nectar_ctx_p->op_mpool == NULL) {
+ RTE_LOG(ERR, USER1, "Nectar: Can't create CRYPTO_OP_POOL\n");
+ return -1;
+ }
+
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_QAT_SYM_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "Nectar: QAT PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_QAT is enabled "
+ "in config file to run this testsuite.\n");
+ return -1;
+ }
+
+ nb_devs = rte_cryptodev_count();
+ if (nb_devs < 1) {
+ RTE_LOG(ERR, USER1, "Nectar: No crypto devices found?\n");
+ return -1;
+ }
+
+ /* 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)
+ nectar_ctx_p->valid_devs[nectar_ctx_p->valid_dev_count++] = i;
+ }
+
+ if (nectar_ctx_p->valid_dev_count < 1)
+ return -1;
+
+ dev_id = nectar_ctx_p->valid_devs[0];
+
+ rte_cryptodev_info_get(dev_id, &info);
+
+ nectar_ctx_p->conf.nb_queue_pairs = info.max_nb_queue_pairs;
+ nectar_ctx_p->conf.socket_id = SOCKET_ID_ANY;
+
+ session_size = rte_cryptodev_get_private_session_size(dev_id);
+
+ /*
+ * Create mempool with maximum number of sessions * 2,
+ * to include the session headers
+ */
+ nectar_ctx_p->session_mpool = rte_mempool_create(
+ "test_sess_mp",
+ info.sym.max_nb_sessions * 2,
+ session_size,
+ 0, 0, NULL, NULL, NULL,
+ NULL, SOCKET_ID_ANY,
+ 0);
+
+ rte_cryptodev_configure(dev_id, &nectar_ctx_p->conf),
+
+ nectar_ctx_p->qp_conf.nb_descriptors = DEFAULT_NUM_OPS_INFLIGHT;
+
+ for (qp_id = 0; qp_id < info.max_nb_queue_pairs; qp_id++) {
+ rte_cryptodev_queue_pair_setup(
+ dev_id, qp_id, &nectar_ctx_p->qp_conf,
+ rte_cryptodev_socket_id(dev_id),
+ nectar_ctx_p->session_mpool);
+ }
+
+ /* Cronstruct the batch return sequence fifo. */
+ //sequence_fifo = rte_ring_create("sequence_fifo", SEQUENCE_FIFO_SIZE, SOCKET_ID_ANY, 0);
+ //if (NULL == sequence_fifo)
+ // rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
+
+
+ cipher2worker = rte_ring_create("cipher2worker_fifo_name", CIPHER2WOKER_FIFO_SIZE, SOCKET_ID_ANY, 0);
+ if (NULL == cipher2worker){
+ printf("Error creating cipher2worker_fifo!\n");
+ return -1;
+ }
+#if 0
+
+#endif
+
+ /*对锁进行初始化*/
+ rte_spinlock_init(&nectar_ctx_p->queue_lock);
+
+// memset(nectar_ctx_p, 0, sizeof(*nectar_ctx_p));
+ /* Start the device */
+ rte_cryptodev_start(nectar_ctx_p->valid_devs[0]);
+
+ running = 1;
+
+ /* 创建线程从qat取加密结果*/
+ retval = rte_eal_remote_launch((lcore_function_t *)nt_crypto_worker, NULL, core);
+ if (retval < 0){
+ rte_exit(EXIT_FAILURE, "Error in rte_eal_remote_launch\n");
+ return retval;
+ }
+
+
+ return 0;
+}
+
+int nt_crypto_init(callback_t callback, uint8_t core){
+ int retval;
+
+ running = 0;
+
+ if(NULL != crypto_ctx){
+ printf("Error: libcrypto is already running\n");
+ return -1;
+ }
+
+ if(NULL == callback)
+ rte_exit(EXIT_FAILURE, "Error callback is NULL!\n");
+
+ /* Create a new nectar crypto context. */
+ crypto_ctx = (crypto_ctx_s*)malloc(sizeof(crypto_ctx_s));
+ if(NULL == crypto_ctx)
+ rte_exit(EXIT_FAILURE, "Error allocating memory for nectar crypto context!\n");
+ memset(crypto_ctx, 0, sizeof(crypto_ctx_s));
+
+ /* Install the callback function. */
+ crypto_ctx->__callback = callback;
+
+ retval = initialize_cryptodevs(core);
+ if(retval < 0) {
+ RTE_LOG(ERR, USER1, "Nectar: initialize_cryptodevs failed.\n");
+ return -1;
+ }
+ rte_spinlock_init(&new_sec_ctx_lock);
+
+ printf("Nectar crypto init ok!\n");
+ return 0;
+}
+
+
+int nt_crypto_end(void){
+ if(0 == running || NULL == crypto_ctx){
+ // printf("Error: libcrypto not running\n");
+ return -1;
+ }
+
+ running = 0;
+
+ /* Give all parth of the library a chance to do work and shutdown. */
+ sleep(1);
+
+ empty_inflight();
+
+ print_stat();
+
+ free(crypto_ctx);
+ crypto_ctx = NULL;
+
+ printf("Nectar crypto has ended!\n");
+ return 0;
+}
+
diff --git a/AAL/qat/libcrypto.h b/AAL/qat/libcrypto.h
new file mode 100644
index 0000000..624e8c4
--- /dev/null
+++ b/AAL/qat/libcrypto.h
@@ -0,0 +1,288 @@
+#ifndef _LIBCRYPTO_H_
+#define _LIBCRYPTO_H_
+
+/** NT libcrypto API version 0.7
+
+version 0.7
+- Performance in 13Gbit/s range - potential limited by virtual channels.
+- Multiple security contexts are now supported.
+- Heavy memory usage, due to worst case return address storrage.
+
+version 0.6
+- ???
+
+The library will encapsulate the Cipher Offload Engine running on the NT SmartNic.
+
+The accelerated functionality can be utilized via the following types and calls:
+*/
+
+#include <stdint.h>
+
+
+
+
+
+#define CRYPTODEV_NAME_QAT_SYM_PMD crypto_qat
+#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
+#define DEFAULT_NUM_OPS_INFLIGHT (128)
+
+
+
+#define TEST_SUCCESS (0)
+#define TEST_FAILED (-1)
+
+#ifndef TEST_TRACE_FAILURE
+# define TEST_TRACE_FAILURE(_file, _line, _func)
+#endif
+
+
+
+#define TEST_ASSERT(cond, msg, ...) do { \
+ if (!(cond)) { \
+ 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_EQUAL(a, b, msg, ...) do { \
+ if (!(a == 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 (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(a, b, msg, ...) do { \
+ if (!(a != 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_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__); \
+ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \
+ return TEST_FAILED; \
+ } \
+} while (0)
+
+#define TEST_ASSERT_FAIL(val, msg, ...) do { \
+ if (!(val != 0)) { \
+ 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_NULL(val, msg, ...) do { \
+ if (!(val == NULL)) { \
+ 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_NULL(val, msg, ...) do { \
+ if (!(val != NULL)) { \
+ printf("TestCase %s() line %d failed: " \
+ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \
+ return TEST_FAILED; \
+ } \
+} while (0)
+
+typedef uint8_t *data_t;
+
+typedef struct {
+ data_t data_in;
+ data_t data_out;
+ uint16_t length;
+ uint8_t pad[2];
+}cipher_input;
+
+#define KEY_SIZE (16)
+#define MAX_BURST_SIZE (32)
+
+#define MAX_SEC_CTX (8) /* The number of concurrently running security contexts. */
+
+#define MAXIMUM_IV_LENGTH (16)
+
+/* The plain- and cipher-text type. */
+
+
+typedef struct {
+ data_t data;
+ uint16_t length;
+} data_out_t;
+
+/* The reference to a security context, which hold the internal state of an encryption tunnel. */
+typedef void *sec_ctx_t;
+
+/* The reference to the data context - will be given with each ciphering and returned with the callback. */
+typedef void *data_ctx_t;
+
+/* The symmetric encryption key. */
+typedef uint8_t symmetric_key_t[KEY_SIZE];
+
+/* The initialization vector. */
+typedef struct __attribute__((packed)) {
+ uint32_t counter;
+ unsigned bearer : 5;
+ unsigned direction : 1;
+ uint8_t padding[3];
+} iv_t;
+
+/* Crypto algorithm selection. */
+typedef enum { LOOPBACK = 0x0, ZUC = 0x3 } algo_type_t;
+
+/*
+The callback for data return.
+
+When the callback returns, the data_out array will be destroyed.
+
+Input:
+- data_ctx : The reference to the data context in which the packet exist.
+- data_out : An array of pointers to data that has been returned.
+- count : The number of array elements in data_out.
+Return:
+- 0 : Operation successful
+- non-zero : Operation failed
+*/
+typedef int (*callback_t)(data_ctx_t data_ctx, data_out_t data_out[MAX_BURST_SIZE], uint16_t count);
+
+/*
+Crypto library initializer
+
+Input:
+- callback : The callback for burst data return.
+- core : The DPDK core used to run the library.
+Return:
+- 0 : Operation successful
+- non-zero : Operation failed
+*/
+int nt_crypto_init(callback_t callback, uint8_t core);
+
+/*
+Setup and return a new security context.
+
+Input:
+- algo_type : Algorithm selection.
+- key : The encryption key.
+- data_ctx : A data context for each PDU encrypted within the security context.
+Return:
+- ptr : A void pointer to the security context.
+- NULL : Operation failed.
+*/
+sec_ctx_t nt_crypto_new_security_context(algo_type_t algo_type, symmetric_key_t key, data_ctx_t data_ctx);
+
+/*
+Encryption and decryption of data:
+
+Input:
+- sec_ctx : The security context, thus key, used to cipher the data.
+- iv : The initialization vector used to cipher the data.
+- cipher_input : The pointer to the input buffer.
+- nb_cipher The number of operations to process.
+ - Return : The number of packets which are ciphered/deciphered successfully.
+*/
+int nt_crypto_cipher(sec_ctx_t sec_ctx, iv_t *iv, cipher_input *crypto_input, uint16_t nb_cipher);
+
+/*
+End a given security context, all in-flight data is lost.
+
+Will return when security context and all related resources has be closed and freed.
+
+Input:
+- sec_ctx : The security context to be closed.
+Return:
+- 0 : Operation successful
+- non-zero : Operation failed
+*/
+int nt_crypto_end_security_context(sec_ctx_t);
+
+/*
+End all security context and stop the crypto library, all in-flight data is lost.
+
+The function will return when all crypto resources has been closed and freed.
+*/
+int nt_crypto_end(void);
+
+
+#endif /* _LIBCRYPTO_H_ */
diff --git a/AAL/qat/libcrypto_test.c b/AAL/qat/libcrypto_test.c
new file mode 100644
index 0000000..bcf732e
--- /dev/null
+++ b/AAL/qat/libcrypto_test.c
@@ -0,0 +1,1015 @@
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <rte_eal.h>
+#include <rte_ethdev.h>
+#include <rte_cycles.h>
+#include <rte_lcore.h>
+#include <rte_mbuf.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "libcrypto.h"
+
+#include "zuc.h"
+
+
+#define DATA_SIZE (1024)
+#define PKT_COUNT (2)
+
+
+/* We need 1 x stat, 1 x libcrypt, min 1 x pdcp */
+#define MIN_CORE_COUNT (3)
+#define MAX_CORE_COUNT (8)
+
+#define US_PER_SEC (1000000)
+
+#define STAT_CORE_ID (0)
+#define LIBCRYPT_CORE_ID (1)
+#define FIRST_PDCP_CORE (2)
+
+#define SPEED_COUNT (14)
+
+volatile uint8_t quit_signal;
+
+static int stat_print(void);
+
+
+
+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 len;
+ } validAuthLenInBits;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } auth_iv;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } 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
+ }
+};
+
+
+
+int null_callback(data_ctx_t data_ctx, data_out_t data_out[MAX_BURST_SIZE], uint16_t burst_count);
+int nectar_zuc_callback(data_ctx_t data_ctx, data_out_t data_out[MAX_BURST_SIZE], uint16_t burst_count);
+int sequence_callback(data_ctx_t data_ctx, data_out_t data_out[MAX_BURST_SIZE], uint16_t burst_count);
+
+static void int_handler(int sig_num) {
+ printf("\nExiting on signal %d\n", sig_num);
+ quit_signal = 1;
+}
+
+uint8_t core_count;
+
+
+typedef struct {
+ uint8_t id;
+ volatile uint64_t pkts_rx;
+ volatile uint64_t pkts_tx;
+
+ volatile uint64_t data_rx;
+ volatile uint64_t data_tx;
+
+ volatile uint64_t next_pkt_sequence;
+} worker_s;
+
+volatile worker_s workers[MAX_CORE_COUNT];
+
+uint32_t callback_pkt_count[MAX_SEC_CTX];
+uint8_t cipher_text [MAX_SEC_CTX][PKT_COUNT][DATA_SIZE];
+
+uint8_t data_in [MAX_SEC_CTX][PKT_COUNT][DATA_SIZE];
+uint8_t data_out [MAX_SEC_CTX][PKT_COUNT][DATA_SIZE];
+
+
+#define TEST_HEXDUMP(file, title, buf, len) rte_hexdump(file, title, buf, len)
+
+
+#if 0
+typedef uint32_t u32;
+typedef uint8_t u8;
+
+
+/*the state registers of LFSR*/
+u32 LFSR_S[16] = {0};
+
+/*the registers of F*/
+u32 F_R1 = 0;
+u32 F_R2 = 0;
+
+/*the outputs of BitReorganization*/
+u32 BRC_X[4] = {0};
+
+/*the s-boxes*/
+u8 S0[256] = {
+ 0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
+ 0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
+ 0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
+ 0xcd,0xc1,0xf8,0x1e,0x73,0x43,0x69,0xc6,0xb5,0xbd,0xfd,0x39,0x63,0x20,0xd4,0x38,
+ 0x76,0x7d,0xb2,0xa7,0xcf,0xed,0x57,0xc5,0xf3,0x2c,0xbb,0x14,0x21,0x06,0x55,0x9b,
+ 0xe3,0xef,0x5e,0x31,0x4f,0x7f,0x5a,0xa4,0x0d,0x82,0x51,0x49,0x5f,0xba,0x58,0x1c,
+ 0x4a,0x16,0xd5,0x17,0xa8,0x92,0x24,0x1f,0x8c,0xff,0xd8,0xae,0x2e,0x01,0xd3,0xad,
+ 0x3b,0x4b,0xda,0x46,0xeb,0xc9,0xde,0x9a,0x8f,0x87,0xd7,0x3a,0x80,0x6f,0x2f,0xc8,
+ 0xb1,0xb4,0x37,0xf7,0x0a,0x22,0x13,0x28,0x7c,0xcc,0x3c,0x89,0xc7,0xc3,0x96,0x56,
+ 0x07,0xbf,0x7e,0xf0,0x0b,0x2b,0x97,0x52,0x35,0x41,0x79,0x61,0xa6,0x4c,0x10,0xfe,
+ 0xbc,0x26,0x95,0x88,0x8a,0xb0,0xa3,0xfb,0xc0,0x18,0x94,0xf2,0xe1,0xe5,0xe9,0x5d,
+ 0xd0,0xdc,0x11,0x66,0x64,0x5c,0xec,0x59,0x42,0x75,0x12,0xf5,0x74,0x9c,0xaa,0x23,
+ 0x0e,0x86,0xab,0xbe,0x2a,0x02,0xe7,0x67,0xe6,0x44,0xa2,0x6c,0xc2,0x93,0x9f,0xf1,
+ 0xf6,0xfa,0x36,0xd2,0x50,0x68,0x9e,0x62,0x71,0x15,0x3d,0xd6,0x40,0xc4,0xe2,0x0f,
+ 0x8e,0x83,0x77,0x6b,0x25,0x05,0x3f,0x0c,0x30,0xea,0x70,0xb7,0xa1,0xe8,0xa9,0x65,
+ 0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60
+};
+
+u8 S1[256] = {
+ 0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
+ 0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
+ 0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
+ 0x3a,0xb5,0x56,0x2a,0xc0,0x6d,0xb3,0x05,0x22,0x66,0xbf,0xdc,0x0b,0xfa,0x62,0x48,
+ 0xdd,0x20,0x11,0x06,0x36,0xc9,0xc1,0xcf,0xf6,0x27,0x52,0xbb,0x69,0xf5,0xd4,0x87,
+ 0x7f,0x84,0x4c,0xd2,0x9c,0x57,0xa4,0xbc,0x4f,0x9a,0xdf,0xfe,0xd6,0x8d,0x7a,0xeb,
+ 0x2b,0x53,0xd8,0x5c,0xa1,0x14,0x17,0xfb,0x23,0xd5,0x7d,0x30,0x67,0x73,0x08,0x09,
+ 0xee,0xb7,0x70,0x3f,0x61,0xb2,0x19,0x8e,0x4e,0xe5,0x4b,0x93,0x8f,0x5d,0xdb,0xa9,
+ 0xad,0xf1,0xae,0x2e,0xcb,0x0d,0xfc,0xf4,0x2d,0x46,0x6e,0x1d,0x97,0xe8,0xd1,0xe9,
+ 0x4d,0x37,0xa5,0x75,0x5e,0x83,0x9e,0xab,0x82,0x9d,0xb9,0x1c,0xe0,0xcd,0x49,0x89,
+ 0x01,0xb6,0xbd,0x58,0x24,0xa2,0x5f,0x38,0x78,0x99,0x15,0x90,0x50,0xb8,0x95,0xe4,
+ 0xd0,0x91,0xc7,0xce,0xed,0x0f,0xb4,0x6f,0xa0,0xcc,0xf0,0x02,0x4a,0x79,0xc3,0xde,
+ 0xa3,0xef,0xea,0x51,0xe6,0x6b,0x18,0xec,0x1b,0x2c,0x80,0xf7,0x74,0xe7,0xff,0x21,
+ 0x5a,0x6a,0x54,0x1e,0x41,0x31,0x92,0x35,0xc4,0x33,0x07,0x0a,0xba,0x7e,0x0e,0x34,
+ 0x88,0xb1,0x98,0x7c,0xf3,0x3d,0x60,0x6c,0x7b,0xca,0xd3,0x1f,0x32,0x65,0x04,0x28,
+ 0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2
+};
+
+/*the constants D*/
+u32 EK_d[16] = {
+ 0x44D7, 0x26BC, 0x626B, 0x135E, 0x5789, 0x35E2, 0x7135, 0x09AF,
+ 0x4D78, 0x2F13, 0x6BC4, 0x1AF1, 0x5E26, 0x3C4D, 0x789A, 0x47AC
+};
+
+u32 AddM(u32 a, u32 b)
+{
+ u32 c = a + b;
+ return (c & 0x7FFFFFFF) + (c >> 31);
+}
+
+/*LFSR with initialization mode*/
+#define MulByPow2(x, k) ((((x) << k) | ((x) >> (31 - k))) & 0x7FFFFFFF)
+void LFSRWithInitializationMode(u32 u)
+{
+ u32 f, v;
+ u32 i;
+
+ f = LFSR_S[0];
+ v = MulByPow2(LFSR_S[0], 8);
+ f = AddM(f, v);
+
+ v = MulByPow2(LFSR_S[4], 20);
+ f = AddM(f, v);
+
+ v = MulByPow2(LFSR_S[10], 21);
+ f = AddM(f, v);
+
+ v = MulByPow2(LFSR_S[13], 17);
+ f = AddM(f, v);
+
+ v = MulByPow2(LFSR_S[15], 15);
+ f = AddM(f, v);
+
+ f = AddM(f, u);
+
+ /*update the state*/
+ for(i=0; i<15; i++)
+ {
+ LFSR_S[i] = LFSR_S[i+1];
+ }
+ LFSR_S[15] = f;
+}
+
+/* LFSR with work mode */
+void LFSRWithWorkMode()
+{
+ u32 f, v;
+ u32 i;
+
+ f = LFSR_S[0];
+ v = MulByPow2(LFSR_S[0], 8);
+ f = AddM(f, v);
+
+ v = MulByPow2(LFSR_S[4], 20);
+ f = AddM(f, v);
+
+ v = MulByPow2(LFSR_S[10], 21);
+ f = AddM(f, v);
+
+ v = MulByPow2(LFSR_S[13], 17);
+ f = AddM(f, v);
+
+ v = MulByPow2(LFSR_S[15], 15);
+ f = AddM(f, v);
+
+ /*update the state*/
+ for(i=0; i<15; i++)
+ {
+ LFSR_S[i] = LFSR_S[i+1];
+ }
+ LFSR_S[15] = f;
+}
+
+/*Bit Reorganization*/
+void BitReorganization()
+{
+ BRC_X[0] = ((LFSR_S[15] & 0x7FFF8000) << 1) | (LFSR_S[14] & 0xFFFF);
+ BRC_X[1] = ((LFSR_S[11] & 0xFFFF) << 16) | (LFSR_S[9] >> 15);
+ BRC_X[2] = ((LFSR_S[7] & 0xFFFF) << 16) | (LFSR_S[5] >> 15);
+ BRC_X[3] = ((LFSR_S[2] & 0xFFFF) << 16) | (LFSR_S[0] >> 15);
+}
+
+#define ROT(a, k) (((a) << k) | ((a) >> (32 - k)))
+
+/*L1*/
+u32 L1(u32 X)
+{
+ return (X ^ ROT(X, 2) ^ ROT(X, 10) ^ ROT(X, 18) ^ ROT(X, 24));
+}
+
+/*L2*/
+u32 L2(u32 X)
+{
+ return (X ^ ROT(X, 8) ^ ROT(X, 14) ^ ROT(X, 22) ^ ROT(X, 30));
+}
+
+#define MAKEU32(a, b, c ,d) (((u32)(a) << 24) | ((u32)(b) << 16) | ((u32)(c) << 8) | ((u32)(d)))
+/*F*/
+u32 F()
+{
+ u32 W, W1, W2, u, v;
+
+ W = (BRC_X[0] ^ F_R1) + F_R2;
+ W1 = F_R1 + BRC_X[1];
+ W2 = F_R2 ^ BRC_X[2];
+ u = L1((W1 << 16) | (W2 >> 16));
+ v = L2((W2 << 16) | (W1 >> 16));
+ F_R1 = MAKEU32(S0[u >> 24], S1[(u >> 16) & 0xFF], S0[(u >> 8) & 0xFF], S1[u & 0xFF]);
+ F_R2 = MAKEU32(S0[v >> 24], S1[(v >> 16) & 0xFF], S0[(v >> 8) & 0xFF], S1[v & 0xFF]);
+
+ return W;
+}
+
+#define MAKEU31(a, b, c) (((u32)((u32)(0) | (u8)(a)) << 23) | ((u32)(b) << 8) | (u32)((u32)(0) | (u8)(c)))
+/*initialize*/
+void Initialization(u8* k, u8* iv)
+{
+ u32 w, nCount;
+ u32 i;
+
+ /* expand key */
+ for (i=0; i<16; i++)
+ {
+ LFSR_S[i] = MAKEU31(k[i], EK_d[i], iv[i]);
+ }
+
+ /*set F_R1 and F_R2 to zero*/
+ F_R1 = 0;
+ F_R2 = 0;
+ nCount = 32;
+ while (nCount > 0)
+ {
+ BitReorganization();
+ w = F();
+ LFSRWithInitializationMode(w >> 1);
+ nCount--;
+ }
+
+ /*First generation, abandoned*/
+ BitReorganization();
+ F();
+ LFSRWithWorkMode();
+}
+
+void GenerateKeyStream(u32 *pKeyStream, u32 KeyStreamLen)
+{
+ u32 i;
+
+ for (i=0; i<KeyStreamLen; i++)
+ {
+ BitReorganization();
+ pKeyStream[i] = F() ^ BRC_X[3];
+ LFSRWithWorkMode();
+ }
+}
+
+
+
+void RevertData(u8 *Data, u32 Len)
+{
+ u32 i = 0;
+ u8 tData = 0;
+
+ for (i=0; i<Len/2; i++)
+ {
+ tData = Data[i];
+ Data[i] = Data[Len-i-1];
+ Data[Len-i-1] = tData;
+ }
+}
+
+int IsLittleEndian()
+{
+ u32 t1 = 0x31;
+
+ if ((*(u8*)(&t1)) == 0x31)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*Length of COUNT is 4*/
+void EEA3_new(u8 *CK, u8 *COUNT, u8 BEARER, u8 DIRECTION, u8 *M, u32 LENGTH, u8 *CM)
+{
+ u8 IV[16] = {0};
+ u32 i = 0, j = 0, tKeyStreamU32 = 0;
+ u8 *tKeyStreamU8 = (u8*)&tKeyStreamU32;
+ u32 bLENGTH = 0; //Byte LENGTH
+ u32 lbLENGTH = 0; //Left Byte LENGTH
+ u8 bMask = 0, bFlag = 0;
+
+ IV[0] = COUNT[0];
+ IV[1] = COUNT[1];
+ IV[2] = COUNT[2];
+ IV[3] = COUNT[3];
+
+ IV[4] = ((BEARER << 3) | ((DIRECTION & 1)<<2)) & 0xFC;
+ IV[5] = IV[6] = IV[7] = 0;
+
+ IV[8] = IV[0];
+ IV[9] = IV[1];
+ IV[10] = IV[2];
+ IV[11] = IV[3];
+ IV[12] = IV[4];
+ IV[13] = IV[5];
+ IV[14] = IV[6];
+ IV[15] = IV[7];
+
+ bLENGTH = LENGTH / 8;
+ lbLENGTH = LENGTH % 8;
+
+ Initialization(CK, IV);
+
+ for (i=0; i<bLENGTH; i++)
+ {
+ if ((i%4) == 0)
+ {
+ GenerateKeyStream(&tKeyStreamU32, 1);
+ if (IsLittleEndian())
+ {
+ RevertData(tKeyStreamU8, 4);
+ }
+ }
+
+ CM[i] = tKeyStreamU8[i%4] ^ M[i];
+ }
+
+ if (lbLENGTH)
+ {
+ if ((i%4) == 0)
+ {
+ GenerateKeyStream(&tKeyStreamU32, 1);
+ if (IsLittleEndian())
+ {
+ RevertData(tKeyStreamU8, 4);
+ }
+ }
+
+ bMask = 0;
+ bFlag = 0x80;
+ for (j=0; j<lbLENGTH; j++)
+ {
+ bMask |= bFlag;
+ bFlag >>= 1;
+ }
+
+ CM[i] = ((tKeyStreamU8[i%4] ^ M[i]) & bMask);
+ }
+}
+
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+static int pdcp_zuc_cipher_worker(void *p) {
+
+ uint64_t worker_id = (uint64_t)p;
+
+ uint32_t i, pkt = 0;
+ int retval = 0;
+
+ iv_t iv[PKT_COUNT];
+ symmetric_key_t sym_key;
+
+ memset(&iv[pkt], 0 , sizeof(iv_t));
+ iv[pkt].counter = (zuc_test_case_cipher_193b.cipher_iv.data[0] << 24);
+ iv[pkt].counter |= zuc_test_case_cipher_193b.cipher_iv.data[1] << 16;
+ iv[pkt].counter |= zuc_test_case_cipher_193b.cipher_iv.data[2] << 8;
+ iv[pkt].counter |= zuc_test_case_cipher_193b.cipher_iv.data[3];
+
+ iv[pkt].bearer = ((zuc_test_case_cipher_193b.cipher_iv.data[4] & 0xF8) >> 3);
+ iv[pkt].direction = (zuc_test_case_cipher_193b.cipher_iv.data[4] & 0x4) >> 2;
+
+ for (pkt = 0; pkt < PKT_COUNT; ++pkt) {
+ for (i = 0; i < DATA_SIZE; ++i) {
+ data_in[worker_id][pkt][i] = zuc_test_case_cipher_193b.plaintext.data[i];
+ }
+ }
+
+ for (i = 0; i < KEY_SIZE; ++i) {
+ sym_key[i] = zuc_test_case_cipher_193b.key.data[i];
+ }
+#if 0
+ pkt = 0;
+// for (pkt = 0; pkt < PKT_COUNT; ++pkt)
+ {
+#if 1
+ memset(cipher_text[worker_id][pkt], 0, zuc_test_case_cipher_193b.plaintext.len/8);
+ EEA3(sym_key, iv[pkt].counter, iv[pkt].bearer, iv[pkt].direction, \
+ zuc_test_case_cipher_193b.plaintext.len, \
+ (uint32_t*)data_in[worker_id][pkt], \
+ (uint32_t*)cipher_text[worker_id][pkt] );
+#else
+#if 0
+ EEA3_new(sym_key, iv[pkt].counter, iv[pkt].bearer, iv[pkt].direction,
+ zuc_test_case_cipher_193b.plaintext.len, (uint32_t*)data_in[worker_id][pkt], (uint32_t*)cipher_text[worker_id][pkt] );
+#else
+
+ EEA3_new(sym_key, &iv[pkt].counter, iv[pkt].bearer, iv[pkt].direction,
+ (u8 *)data_in[worker_id][pkt], zuc_test_case_cipher_193b.plaintext.len, (u8 *)cipher_text[worker_id][pkt] );
+#endif
+#endif
+
+ TEST_HEXDUMP(stdout, "key:", sym_key, KEY_SIZE);
+ TEST_HEXDUMP(stdout, "plaintext:", data_in, zuc_test_case_cipher_193b.plaintext.len/8);
+ TEST_HEXDUMP(stdout, "ciphertext:", cipher_text[worker_id][pkt], zuc_test_case_cipher_193b.plaintext.len/8);
+
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ &cipher_text[worker_id][pkt],
+ zuc_test_case_cipher_193b.ciphertext.data,
+ zuc_test_case_cipher_193b.validDataLenInBits.len,
+ "ZUC Ciphertext data not as expected");
+ printf("xxxxxxxxxxxxxx Nectar zuc cipher as expected\n");
+ }
+#endif
+
+
+ //data_ctx_t data_ctx = (data_ctx_t)worker_id+34;
+ data_ctx_t data_ctx = 0x34;
+ sec_ctx_t sec_ctx = nt_crypto_new_security_context(ZUC, sym_key, data_ctx);
+ if(NULL == sec_ctx){
+ printf("Error creating new security context!\n");
+ return -1;
+ }
+
+ sec_ctx_t sec_ctx2 = nt_crypto_new_security_context(ZUC, sym_key, data_ctx);
+ if(NULL == sec_ctx){
+ printf("Error creating new security context!\n");
+ return -1;
+ }
+
+ pkt = 0;
+ callback_pkt_count[worker_id] = 0;
+
+ // uint16_t len = 0;
+
+ int _signal = 20000001;
+ //int _signal = 640;
+ while ((_signal--) ) {
+
+
+ retval = nt_crypto_cipher(sec_ctx, &iv[pkt], data_in[worker_id][pkt], data_out[worker_id][pkt],
+ zuc_test_case_cipher_193b.plaintext.len/8);
+ if( unlikely(retval) ){
+ printf("nt_crypto_cipher did not cipher!?!\n");
+ continue;
+ }
+ workers[worker_id].pkts_tx++;
+ //rte_pause();
+// printf("_signal = %d\n", _signal);
+// pkt = (pkt + 1) % PKT_COUNT;
+ }
+ quit_signal = 0;
+
+ printf("xxxxxxxxxxxxxxxxx _signal = %d\n", _signal);
+ return 0;
+}
+
+
+int nectar_zuc_callback(data_ctx_t data_ctx, data_out_t data_out[MAX_BURST_SIZE], uint16_t burst_count) {
+
+ static int count = 1;
+ uint64_t idx = (uint64_t)data_ctx;
+ workers[idx].pkts_rx += burst_count;
+
+ int retval = 0;
+
+ TEST_HEXDUMP(stdout, "data out:", data_out[0].data, data_out[0].length);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ data_out[0].data,
+ zuc_test_case_cipher_193b.ciphertext.data,
+ zuc_test_case_cipher_193b.validDataLenInBits.len,
+ "ZUC Ciphertext data not as expected");
+ printf("Nectar zuc cipher as expected %d times\n", count++);
+
+#if 0
+ for ( j = 0; j < burst_count; ++j) {
+ workers[idx].data_rx += data_out[j].length;
+
+ // printf("got len: %d\n", data_out[j].length);
+ for (i = 0; i < data_out[i].length; ++i) {
+ // for (i = 0; i < 4; ++i) {
+
+ if(data_out[j].data[i] != cipher_text[idx][ callback_pkt_count[idx] ][i] ) {
+ //printf("\nError in callback: plain != cipher: %02x != %02x\n", data_out[j].data[i], cipher_text[idx][0][i] );
+
+ printf("worker %ld with pkt %d has len: %d\n", idx, callback_pkt_count[idx], data_out[j].length);
+ printf("Expected:\n");
+ for (k = 0; k < data_out[j].length; ++k) {
+ printf("%02x ", cipher_text[idx][ callback_pkt_count[idx] ][k]);
+ }
+ printf("\ngot: \n");
+ for (k = 0; k < data_out[j].length; ++k) {
+ printf("%02x ", data_out[j].data[k]);
+ }
+ printf("\n");
+
+ if(0 != j){
+ printf("length of prev: %d\n", data_out[j-1].length);
+ }
+
+ retval = -1;
+ // return -1;
+ }
+ }
+ callback_pkt_count[idx] = (callback_pkt_count[idx] + 1) % PKT_COUNT;
+ }
+ // printf("\n");
+
+#endif
+ return retval;
+}
+
+int main(int argc, char *argv[]) {
+
+ uint8_t portid, core;
+ quit_signal = 0;
+
+ /* Catch ctrl-c so we can print on exit. */
+ signal(SIGINT, int_handler);
+
+ // srand(4);
+
+ /* Initialize the Environment Abstraction Layer (EAL). */
+ int ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+
+ argc -= ret;
+ argv += ret;
+
+ core_count = rte_lcore_count();
+ if ( MIN_CORE_COUNT > core_count ) {
+ printf("\nERROR: Need at least %i cores.\n", MIN_CORE_COUNT);
+ return -1;
+ }
+
+ uint8_t nb_ports = rte_eth_dev_count();
+
+ // int retval = nt_crypto_init(null_callback, LIBCRYPT_CORE_ID);
+ int retval = nt_crypto_init(nectar_zuc_callback, LIBCRYPT_CORE_ID);
+ // int retval = nt_crypto_init(sequence_callback, LIBCRYPT_CORE_ID);
+ if(retval){
+ printf("Error in nt_crypto_init\n");
+ return -1;
+ }
+
+ /* Start security contexts from the first free core - after the libcrypto thread. */
+ //for (core = FIRST_PDCP_CORE; core < core_count; ++core) {
+ for (core = FIRST_PDCP_CORE; core < FIRST_PDCP_CORE +1; ++core) {
+ printf("Launching worker on core: %d\n", core);
+ uint64_t idx = core - FIRST_PDCP_CORE;
+ rte_eal_remote_launch((lcore_function_t *)pdcp_zuc_cipher_worker, (void*)idx, core);
+
+ usleep(10000);
+ }
+
+// stat_print();
+
+
+
+ RTE_LCORE_FOREACH_SLAVE(core) {
+ if (rte_eal_wait_lcore(core) < 0)
+ return -1;
+ }
+
+ nt_crypto_end();
+ for (portid = 0; portid < nb_ports; portid++) {
+ printf("Closing port %i\n", portid);
+ rte_eth_dev_stop(portid);
+ rte_eth_dev_close(portid);
+ }
+ return 0;
+}
+
+
+static int stat_print(void) {
+
+ uint64_t total_pkt_tx;
+ uint64_t total_pkt_rx;
+
+ uint64_t total_data_rx;
+ uint64_t prev_total_data_rx = 0;
+
+ // uint64_t prev_total_pkt_tx = 0;
+
+ while ( !quit_signal ) {
+ sleep(1);
+
+ total_pkt_tx = 0;
+ total_pkt_rx = 0;
+ total_data_rx = 0;
+
+ uint8_t i;
+ for (i = 0; i < core_count; ++i) {
+ total_pkt_tx += workers[i].pkts_tx;
+ total_pkt_rx += workers[i].pkts_rx;
+
+ total_data_rx += workers[i].data_rx;
+ }
+
+ // uint64_t packets_1_sec = total_pkt_tx - prev_total_pkt_tx;
+ // prev_total_pkt_tx = total_pkt_tx;
+
+ uint64_t byte_per_sec = total_data_rx - prev_total_data_rx;
+ prev_total_data_rx = total_data_rx;
+
+ double mbps = (byte_per_sec * 8 ) / 1000.0 / 1000.0;
+ double mpps = (mbps / 8.0) / DATA_SIZE;
+ printf("TX: %ld\tRX: %ld\tinflight: %ld\tbw: %0.0f Mb/s\tmpps: %0.1f\n", total_pkt_tx, total_pkt_rx, total_pkt_tx - total_pkt_rx, mbps, mpps );
+
+ }
+
+ return 0;
+}
diff --git a/AAL/qat/main.c b/AAL/qat/main.c
new file mode 100644
index 0000000..e89e2e1
--- /dev/null
+++ b/AAL/qat/main.c
@@ -0,0 +1,763 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdbool.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_eal.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.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>
+
+static volatile bool force_quit;
+
+/* MAC updating enabled by default */
+static int mac_updating = 1;
+
+#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
+
+#define NB_MBUF 8192
+
+#define MAX_PKT_BURST 32
+#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
+#define MEMPOOL_CACHE_SIZE 256
+
+/*
+ * Configurable number of RX/TX ring descriptors
+ */
+#define RTE_TEST_RX_DESC_DEFAULT 128
+#define RTE_TEST_TX_DESC_DEFAULT 512
+static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
+static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
+
+/* ethernet addresses of ports */
+static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
+
+/* mask of enabled ports */
+static uint32_t l2fwd_enabled_port_mask = 0;
+
+/* list of enabled ports */
+static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];
+
+static unsigned int l2fwd_rx_queue_per_lcore = 1;
+
+#define MAX_RX_QUEUE_PER_LCORE 16
+#define MAX_TX_QUEUE_PER_PORT 16
+struct lcore_queue_conf {
+ unsigned n_rx_port;
+ unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];
+} __rte_cache_aligned;
+struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
+
+static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];
+
+static const struct rte_eth_conf port_conf = {
+ .rxmode = {
+ .split_hdr_size = 0,
+ .header_split = 0, /**< Header Split disabled */
+ .hw_ip_checksum = 0, /**< IP checksum offload disabled */
+ .hw_vlan_filter = 0, /**< VLAN filtering disabled */
+ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */
+ .hw_strip_crc = 1, /**< CRC stripped by hardware */
+ },
+ .txmode = {
+ .mq_mode = ETH_MQ_TX_NONE,
+ },
+};
+
+struct rte_mempool * l2fwd_pktmbuf_pool = NULL;
+
+/* Per-port statistics struct */
+struct l2fwd_port_statistics {
+ uint64_t tx;
+ uint64_t rx;
+ uint64_t dropped;
+} __rte_cache_aligned;
+struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];
+
+#define MAX_TIMER_PERIOD 86400 /* 1 day max */
+/* A tsc-based timer responsible for triggering statistics printout */
+static uint64_t timer_period = 10; /* default period is 10 seconds */
+
+/* Print out statistics on packets dropped */
+static void
+print_stats(void)
+{
+ uint64_t total_packets_dropped, total_packets_tx, total_packets_rx;
+ unsigned portid;
+
+ total_packets_dropped = 0;
+ total_packets_tx = 0;
+ total_packets_rx = 0;
+
+ const char clr[] = { 27, '[', '2', 'J', '\0' };
+ const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' };
+
+ /* Clear screen and move to top left */
+ printf("%s%s", clr, topLeft);
+
+ printf("\nPort statistics ====================================");
+
+ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
+ /* skip disabled ports */
+ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
+ continue;
+ printf("\nStatistics for port %u ------------------------------"
+ "\nPackets sent: %24"PRIu64
+ "\nPackets received: %20"PRIu64
+ "\nPackets dropped: %21"PRIu64,
+ portid,
+ port_statistics[portid].tx,
+ port_statistics[portid].rx,
+ port_statistics[portid].dropped);
+
+ total_packets_dropped += port_statistics[portid].dropped;
+ total_packets_tx += port_statistics[portid].tx;
+ total_packets_rx += port_statistics[portid].rx;
+ }
+ printf("\nAggregate statistics ==============================="
+ "\nTotal packets sent: %18"PRIu64
+ "\nTotal packets received: %14"PRIu64
+ "\nTotal packets dropped: %15"PRIu64,
+ total_packets_tx,
+ total_packets_rx,
+ total_packets_dropped);
+ printf("\n====================================================\n");
+}
+
+static void
+l2fwd_mac_updating(struct rte_mbuf *m, unsigned dest_portid)
+{
+ struct ether_hdr *eth;
+ void *tmp;
+
+ eth = rte_pktmbuf_mtod(m, struct ether_hdr *);
+
+ /* 02:00:00:00:00:xx */
+ tmp = &eth->d_addr.addr_bytes[0];
+ *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dest_portid << 40);
+
+ /* src addr */
+ ether_addr_copy(&l2fwd_ports_eth_addr[dest_portid], &eth->s_addr);
+}
+
+static void
+l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)
+{
+ unsigned dst_port;
+ int sent;
+ struct rte_eth_dev_tx_buffer *buffer;
+
+ dst_port = l2fwd_dst_ports[portid];
+
+ if (mac_updating)
+ l2fwd_mac_updating(m, dst_port);
+
+ buffer = tx_buffer[dst_port];
+ sent = rte_eth_tx_buffer(dst_port, 0, buffer, m);
+ if (sent)
+ port_statistics[dst_port].tx += sent;
+}
+
+/* main processing loop */
+static void
+l2fwd_main_loop(void)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_mbuf *m;
+ int sent;
+ unsigned lcore_id;
+ uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;
+ unsigned i, j, portid, nb_rx;
+ struct lcore_queue_conf *qconf;
+ const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S *
+ BURST_TX_DRAIN_US;
+ struct rte_eth_dev_tx_buffer *buffer;
+
+ prev_tsc = 0;
+ timer_tsc = 0;
+
+ lcore_id = rte_lcore_id();
+ qconf = &lcore_queue_conf[lcore_id];
+
+ if (qconf->n_rx_port == 0) {
+ RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id);
+ return;
+ }
+
+ RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id);
+
+ for (i = 0; i < qconf->n_rx_port; i++) {
+
+ portid = qconf->rx_port_list[i];
+ RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id,
+ portid);
+
+ }
+
+ while (!force_quit) {
+
+ cur_tsc = rte_rdtsc();
+
+ /*
+ * TX burst queue drain
+ */
+ diff_tsc = cur_tsc - prev_tsc;
+ if (unlikely(diff_tsc > drain_tsc)) {
+
+ for (i = 0; i < qconf->n_rx_port; i++) {
+
+ portid = l2fwd_dst_ports[qconf->rx_port_list[i]];
+ buffer = tx_buffer[portid];
+
+ sent = rte_eth_tx_buffer_flush(portid, 0, buffer);
+ if (sent)
+ port_statistics[portid].tx += sent;
+
+ }
+
+ /* if timer is enabled */
+ if (timer_period > 0) {
+
+ /* advance the timer */
+ timer_tsc += diff_tsc;
+
+ /* if timer has reached its timeout */
+ if (unlikely(timer_tsc >= timer_period)) {
+
+ /* do this only on master core */
+ if (lcore_id == rte_get_master_lcore()) {
+ print_stats();
+ /* reset the timer */
+ timer_tsc = 0;
+ }
+ }
+ }
+
+ prev_tsc = cur_tsc;
+ }
+
+ /*
+ * Read packet from RX queues
+ */
+ for (i = 0; i < qconf->n_rx_port; i++) {
+
+ portid = qconf->rx_port_list[i];
+ nb_rx = rte_eth_rx_burst(portid, 0,
+ pkts_burst, MAX_PKT_BURST);
+
+ port_statistics[portid].rx += nb_rx;
+
+ for (j = 0; j < nb_rx; j++) {
+ m = pkts_burst[j];
+ rte_prefetch0(rte_pktmbuf_mtod(m, void *));
+ l2fwd_simple_forward(m, portid);
+ }
+ }
+ }
+}
+
+static int
+l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy)
+{
+ l2fwd_main_loop();
+ return 0;
+}
+
+/* display usage */
+static void
+l2fwd_usage(const char *prgname)
+{
+ printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n"
+ " -p PORTMASK: hexadecimal bitmask of ports to configure\n"
+ " -q NQ: number of queue (=ports) per lcore (default is 1)\n"
+ " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n"
+ " --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n"
+ " When enabled:\n"
+ " - The source MAC address is replaced by the TX port MAC address\n"
+ " - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n",
+ prgname);
+}
+
+static int
+l2fwd_parse_portmask(const char *portmask)
+{
+ char *end = NULL;
+ unsigned long pm;
+
+ /* parse hexadecimal string */
+ pm = strtoul(portmask, &end, 16);
+ if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
+ return -1;
+
+ if (pm == 0)
+ return -1;
+
+ return pm;
+}
+
+static unsigned int
+l2fwd_parse_nqueue(const char *q_arg)
+{
+ char *end = NULL;
+ unsigned long n;
+
+ /* parse hexadecimal string */
+ n = strtoul(q_arg, &end, 10);
+ if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
+ return 0;
+ if (n == 0)
+ return 0;
+ if (n >= MAX_RX_QUEUE_PER_LCORE)
+ return 0;
+
+ return n;
+}
+
+static int
+l2fwd_parse_timer_period(const char *q_arg)
+{
+ char *end = NULL;
+ int n;
+
+ /* parse number string */
+ n = strtol(q_arg, &end, 10);
+ if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
+ return -1;
+ if (n >= MAX_TIMER_PERIOD)
+ return -1;
+
+ return n;
+}
+
+static const char short_options[] =
+ "p:" /* portmask */
+ "q:" /* number of queues */
+ "T:" /* timer period */
+ ;
+
+#define CMD_LINE_OPT_MAC_UPDATING "mac-updating"
+#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating"
+
+enum {
+ /* long options mapped to a short option */
+
+ /* first long only option value must be >= 256, so that we won't
+ * conflict with short options */
+ CMD_LINE_OPT_MIN_NUM = 256,
+};
+
+static const struct option lgopts[] = {
+ { CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1},
+ { CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0},
+ {NULL, 0, 0, 0}
+};
+
+/* Parse the argument given in the command line of the application */
+static int
+l2fwd_parse_args(int argc, char **argv)
+{
+ int opt, ret, timer_secs;
+ char **argvopt;
+ int option_index;
+ char *prgname = argv[0];
+
+ argvopt = argv;
+
+ while ((opt = getopt_long(argc, argvopt, short_options,
+ lgopts, &option_index)) != EOF) {
+
+ switch (opt) {
+ /* portmask */
+ case 'p':
+ l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg);
+ if (l2fwd_enabled_port_mask == 0) {
+ printf("invalid portmask\n");
+ l2fwd_usage(prgname);
+ return -1;
+ }
+ break;
+
+ /* nqueue */
+ case 'q':
+ l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg);
+ if (l2fwd_rx_queue_per_lcore == 0) {
+ printf("invalid queue number\n");
+ l2fwd_usage(prgname);
+ return -1;
+ }
+ break;
+
+ /* timer period */
+ case 'T':
+ timer_secs = l2fwd_parse_timer_period(optarg);
+ if (timer_secs < 0) {
+ printf("invalid timer period\n");
+ l2fwd_usage(prgname);
+ return -1;
+ }
+ timer_period = timer_secs;
+ break;
+
+ /* long options */
+ case 0:
+ break;
+
+ default:
+ l2fwd_usage(prgname);
+ return -1;
+ }
+ }
+
+ if (optind >= 0)
+ argv[optind-1] = prgname;
+
+ ret = optind-1;
+ optind = 1; /* reset getopt lib */
+ return ret;
+}
+
+/* Check the link status of all ports in up to 9s, 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 90 /* 9s (90 * 100ms) in total */
+ uint16_t portid;
+ uint8_t count, all_ports_up, print_flag = 0;
+ struct rte_eth_link link;
+
+ printf("\nChecking link status");
+ fflush(stdout);
+ for (count = 0; count <= MAX_CHECK_TIME; count++) {
+ if (force_quit)
+ return;
+ all_ports_up = 1;
+ for (portid = 0; portid < port_num; portid++) {
+ if (force_quit)
+ return;
+ if ((port_mask & (1 << portid)) == 0)
+ continue;
+ memset(&link, 0, sizeof(link));
+ rte_eth_link_get_nowait(portid, &link);
+ /* 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\n"));
+ 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) {
+ printf(".");
+ 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;
+ printf("done\n");
+ }
+ }
+}
+
+static void
+signal_handler(int signum)
+{
+ if (signum == SIGINT || signum == SIGTERM) {
+ printf("\n\nSignal %d received, preparing to exit...\n",
+ signum);
+ force_quit = true;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ struct lcore_queue_conf *qconf;
+ struct rte_eth_dev_info dev_info;
+ int ret;
+ uint16_t nb_ports;
+ uint16_t nb_ports_available;
+ uint16_t portid, last_port;
+ unsigned lcore_id, rx_lcore_id;
+ unsigned nb_ports_in_mask = 0;
+
+ /* init EAL */
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
+ argc -= ret;
+ argv += ret;
+
+ force_quit = false;
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+
+ /* parse application arguments (after the EAL ones) */
+ ret = l2fwd_parse_args(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n");
+
+ printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled");
+
+ /* convert to number of cycles */
+ timer_period *= rte_get_timer_hz();
+
+ /* create the mbuf pool */
+ l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF,
+ MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
+ rte_socket_id());
+ if (l2fwd_pktmbuf_pool == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
+
+ nb_ports = rte_eth_dev_count();
+ if (nb_ports == 0)
+ rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
+
+ /* reset l2fwd_dst_ports */
+ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
+ l2fwd_dst_ports[portid] = 0;
+ last_port = 0;
+
+ /*
+ * Each logical core is assigned a dedicated TX queue on each port.
+ */
+ for (portid = 0; portid < nb_ports; portid++) {
+ /* skip ports that are not enabled */
+ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
+ continue;
+
+ if (nb_ports_in_mask % 2) {
+ l2fwd_dst_ports[portid] = last_port;
+ l2fwd_dst_ports[last_port] = portid;
+ }
+ else
+ last_port = portid;
+
+ nb_ports_in_mask++;
+
+ rte_eth_dev_info_get(portid, &dev_info);
+ }
+ if (nb_ports_in_mask % 2) {
+ printf("Notice: odd number of ports in portmask.\n");
+ l2fwd_dst_ports[last_port] = last_port;
+ }
+
+ rx_lcore_id = 0;
+ qconf = NULL;
+
+ /* Initialize the port/queue configuration of each logical core */
+ for (portid = 0; portid < nb_ports; portid++) {
+ /* skip ports that are not enabled */
+ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
+ continue;
+
+ /* get the lcore_id for this port */
+ while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
+ lcore_queue_conf[rx_lcore_id].n_rx_port ==
+ l2fwd_rx_queue_per_lcore) {
+ rx_lcore_id++;
+ if (rx_lcore_id >= RTE_MAX_LCORE)
+ rte_exit(EXIT_FAILURE, "Not enough cores\n");
+ }
+
+ if (qconf != &lcore_queue_conf[rx_lcore_id])
+ /* Assigned a new logical core in the loop above. */
+ qconf = &lcore_queue_conf[rx_lcore_id];
+
+ qconf->rx_port_list[qconf->n_rx_port] = portid;
+ qconf->n_rx_port++;
+ printf("Lcore %u: RX port %u\n", rx_lcore_id, portid);
+ }
+
+ nb_ports_available = nb_ports;
+
+ /* Initialise each port */
+ for (portid = 0; portid < nb_ports; portid++) {
+ /* skip ports that are not enabled */
+ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) {
+ printf("Skipping disabled port %u\n", portid);
+ nb_ports_available--;
+ continue;
+ }
+ /* init port */
+ printf("Initializing port %u... ", portid);
+ fflush(stdout);
+ ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n",
+ ret, portid);
+
+ ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
+ &nb_txd);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "Cannot adjust number of descriptors: err=%d, port=%u\n",
+ ret, portid);
+
+ rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]);
+
+ /* init one RX queue */
+ fflush(stdout);
+ ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
+ rte_eth_dev_socket_id(portid),
+ NULL,
+ l2fwd_pktmbuf_pool);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n",
+ ret, portid);
+
+ /* init one TX queue on each port */
+ fflush(stdout);
+ ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
+ rte_eth_dev_socket_id(portid),
+ NULL);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n",
+ ret, portid);
+
+ /* Initialize TX buffers */
+ tx_buffer[portid] = rte_zmalloc_socket("tx_buffer",
+ RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
+ rte_eth_dev_socket_id(portid));
+ if (tx_buffer[portid] == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n",
+ portid);
+
+ rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST);
+
+ ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid],
+ rte_eth_tx_buffer_count_callback,
+ &port_statistics[portid].dropped);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "Cannot set error callback for tx buffer on port %u\n",
+ portid);
+
+ /* Start device */
+ ret = rte_eth_dev_start(portid);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n",
+ ret, portid);
+
+ printf("done: \n");
+
+ rte_eth_promiscuous_enable(portid);
+
+ printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
+ portid,
+ l2fwd_ports_eth_addr[portid].addr_bytes[0],
+ l2fwd_ports_eth_addr[portid].addr_bytes[1],
+ l2fwd_ports_eth_addr[portid].addr_bytes[2],
+ l2fwd_ports_eth_addr[portid].addr_bytes[3],
+ l2fwd_ports_eth_addr[portid].addr_bytes[4],
+ l2fwd_ports_eth_addr[portid].addr_bytes[5]);
+
+ /* initialize port stats */
+ memset(&port_statistics, 0, sizeof(port_statistics));
+ }
+
+ if (!nb_ports_available) {
+ rte_exit(EXIT_FAILURE,
+ "All available ports are disabled. Please set portmask.\n");
+ }
+
+ check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask);
+
+ ret = 0;
+ /* launch per-lcore init on every lcore */
+ rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MASTER);
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (rte_eal_wait_lcore(lcore_id) < 0) {
+ ret = -1;
+ break;
+ }
+ }
+
+ for (portid = 0; portid < nb_ports; portid++) {
+ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
+ continue;
+ printf("Closing port %d...", portid);
+ rte_eth_dev_stop(portid);
+ rte_eth_dev_close(portid);
+ printf(" Done\n");
+ }
+ printf("Bye...\n");
+
+ return ret;
+}
diff --git a/AAL/qat/pdcp.c b/AAL/qat/pdcp.c
new file mode 100644
index 0000000..8ad25d1
--- /dev/null
+++ b/AAL/qat/pdcp.c
@@ -0,0 +1,660 @@
+#include <stdint.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <rte_eal.h>
+#include <rte_ethdev.h>
+#include <rte_cycles.h>
+#include <rte_lcore.h>
+#include <rte_mbuf.h>
+
+#include <rte_ring.h> // fifo's
+#include <rte_errno.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "libcrypto.h"
+
+// #include "zuc.h"
+
+
+/* PDCP need the following cores: 1 x stat, 1 x libcrypt, min 1 x pdcp */
+#define MIN_CORE_COUNT (4)
+#define MAX_CORE_COUNT (8)
+
+#define US_PER_SEC (1000000)
+
+#define STAT_CORE_ID (0)
+#define LIBCRYPT_CORE_ID (1)
+#define DIST_CORE (2)
+#define FIRST_PDCP_CORE (3)
+
+
+/* Internal DPDK info */
+#define PRIV_SIZE (0)
+#define MBUF_SIZE (10000)
+#define MBUF_CACHE_SIZE (250)
+#define MBUF_COUNT (4096)
+
+#define TX_QUEUE_ID (0)
+#define RX_QUEUE_ID (0)
+
+#define RX_RING_SIZE (1024)
+#define TX_RING_SIZE (1024)
+
+#define RX_BURST_SIZE (16)
+
+/* Batch memory management system */
+#define IN_FIFO_SIZE (4096*2)
+#define OUT_FIFO_SIZE (4096*2)
+#define CALLBACK_FIFO_SIZE (4096*2)
+
+
+/* .'.--.'. */
+
+volatile uint8_t quit_signal;
+static void int_handler(int sig_num) {
+ printf("\nExiting on signal %d\n", sig_num);
+ quit_signal = 1;
+}
+
+
+static int stat_print(void);
+int init_pdcp(void);
+int callback(data_ctx_t data_ctx, data_out_t data_out[MAX_BURST_SIZE], uint16_t burst_count);
+int dist_worker(void *p);
+
+
+/* System variables */
+
+typedef struct {
+ struct rte_mbuf *pkt;
+ void *last_address;
+} return_batch_s;
+
+
+typedef struct {
+ struct rte_ring *in_fifo;
+ struct rte_ring *out_fifo;
+ return_batch_s *current_return_batch;
+} worker_s;
+
+uint8_t worker_count;
+worker_s workers[MAX_CORE_COUNT];
+
+typedef struct {
+ volatile uint64_t start_time;
+ volatile uint64_t util_time;
+
+ volatile uint64_t pkts_in;
+ volatile uint64_t pkts_out;
+
+ volatile uint64_t data_out;
+ volatile uint64_t data_in;
+
+} status_s;
+
+
+volatile uint64_t init_time;
+
+volatile status_s status[MAX_CORE_COUNT];
+
+struct rte_mempool *mbuf_pool;
+
+struct rte_ring *callback_fifo;
+
+
+int init_pdcp(void) {
+
+ int retval = 0;
+ uint8_t pid;
+
+ mbuf_pool = rte_pktmbuf_pool_create( "MBUF_PDCP_POOL",
+ MBUF_COUNT,
+ MBUF_CACHE_SIZE,
+ PRIV_SIZE,
+ MBUF_SIZE + RTE_PKTMBUF_HEADROOM,
+ rte_socket_id());
+
+ if (NULL == mbuf_pool)
+ rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
+
+ struct ether_addr addr;
+
+ const struct rte_eth_conf port_conf = {
+ .rxmode = {
+ .max_rx_pkt_len = ETHER_MAX_LEN,
+ .split_hdr_size = 0,
+ .header_split = 0, /**< Header Split disabled */
+ .hw_ip_checksum = 0, /**< IP checksum offload disabled */
+ .hw_vlan_filter = 0, /**< VLAN filtering disabled */
+ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */
+ .hw_strip_crc = 1, /**< CRC stripped by hardware */
+ },
+ };
+
+ uint8_t nb_ports = rte_eth_dev_count();
+
+ /* Initialize all ports. */
+ for (pid = 0; pid < nb_ports; pid++){
+
+ /* Get and display the port MAC address. */
+ rte_eth_macaddr_get(pid, &addr);
+ if(0xff == addr.addr_bytes[3]){
+ // printf("Found libcrypto port at %d\n", pid);
+ continue;
+ }
+
+ /* Configure the Ethernet device. */
+ retval = rte_eth_dev_configure(pid, 1, 1, &port_conf);
+ if (retval != 0) {
+ rte_exit(EXIT_FAILURE, "Error in rte_eth_dev_configure\n");
+ return retval;
+ }
+
+ retval = rte_eth_rx_queue_setup(pid, RX_QUEUE_ID, RX_RING_SIZE, rte_eth_dev_socket_id(pid), NULL, mbuf_pool);
+ if (retval < 0){
+ rte_exit(EXIT_FAILURE, "Error in rte_eth_rx_queue_setup\n");
+ return retval;
+ }
+
+ retval = rte_eth_tx_queue_setup(pid, TX_QUEUE_ID, TX_RING_SIZE, rte_eth_dev_socket_id(pid), NULL);
+ if (retval < 0){
+ rte_exit(EXIT_FAILURE, "Error in rte_eth_tx_queue_setup\n");
+ return retval;
+ }
+
+ /* Start the port. */
+ retval = rte_eth_dev_start(pid);
+ if (retval < 0){
+ rte_exit(EXIT_FAILURE, "Error in rte_eth_dev_start\n");
+ return retval;
+ }
+
+ printf("port %d has started\n", pid);
+ }
+
+ callback_fifo = rte_ring_create("callback_fifo_name", CALLBACK_FIFO_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (NULL == callback_fifo){
+ printf("Error creating callback_fifo!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int callback(data_ctx_t data_ctx, data_out_t data_out[MAX_BURST_SIZE], uint16_t burst_count) {
+
+ uint8_t tx_port_id = 0;
+
+ int retval;
+ void *fifo_return_data[1];
+ uint64_t wid = (uint64_t)data_ctx;
+
+
+ // printf("callback for worker %ld\n", wid);
+
+ if (NULL == workers[wid].current_return_batch) {
+
+ while (rte_ring_empty(workers[wid].out_fifo)){
+ if ( unlikely(quit_signal) ) return 0;
+ }
+
+ retval = rte_ring_dequeue(workers[wid].out_fifo, fifo_return_data);
+ if( unlikely(retval) ){
+ rte_exit(EXIT_FAILURE, "Received batch with empty sequence FIFO !!!\n");
+ }
+
+ workers[wid].current_return_batch = (return_batch_s*)fifo_return_data[0];
+ }
+
+ // status[wid].pkts_out += burst_count;
+
+ int i;
+ for (i = 0; i < burst_count; ++i) {
+ // status[wid].data_out += data_out[i].length;
+
+
+ uint64_t *data = (uint64_t *)data_out[i].data;
+
+ /* If the data is the last pkt in a batch, Tx it out now! */
+ if( data == workers[wid].current_return_batch->last_address ){
+
+ // printf("Last address found - Tx time!!\n");
+
+ status[wid].pkts_out++;
+
+ /* Restore the batch header from the buffer. */
+ rte_pktmbuf_prepend(workers[wid].current_return_batch->pkt, sizeof(struct rte_mbuf_batch_pkt_hdr));
+
+
+ /* Store the data return address on the queue. */
+ while (rte_ring_full(callback_fifo)) {
+ printf("callback_fifo is full!!!\n");
+ if ( unlikely(quit_signal) ){
+ return -1;
+ }
+ }
+ retval = rte_ring_enqueue(callback_fifo, workers[wid].current_return_batch->pkt);
+ if( unlikely(0 != retval) ){
+ rte_exit(EXIT_FAILURE, "Error in rte_ring_enqueue into return_addr_fifo\n");
+ }
+
+
+ // uint16_t nb_tx = 0;
+ // do {
+ // if ( unlikely(quit_signal) ){
+ // return -1;
+ // }
+ // nb_tx = rte_eth_tx_burst(tx_port_id, TX_QUEUE_ID, &workers[wid].current_return_batch->pkt, 1);
+ // } while( unlikely(0 == nb_tx) );
+
+ // rte_pktmbuf_free(workers[wid].current_return_batch->pkt);
+
+ free(workers[wid].current_return_batch);
+
+ /* Get the next return batch. */
+ /*
+ If the traffic stop, this point can deadlock the system.
+ This loop will wait for new return batch, which will hold back all other sec_ctxs.
+ */
+ while (rte_ring_empty(workers[wid].out_fifo)){
+
+ if(i == burst_count - 1){
+ // printf("Last batch wid: %d\n", wid);
+ workers[wid].current_return_batch = NULL;
+ return 0;
+ }
+
+ printf("No batch in fifo\n");
+ if ( unlikely(quit_signal) ) return 0;
+ }
+
+ retval = rte_ring_dequeue(workers[wid].out_fifo, fifo_return_data);
+ if( unlikely(retval) ){
+ rte_exit(EXIT_FAILURE, "Received batch with empty sequence FIFO !!!\n");
+ }
+
+ workers[wid].current_return_batch = (return_batch_s*)fifo_return_data[0];
+ }
+ }
+
+ return 0;
+}
+
+
+static int pdcp_worker(void *p) {
+ uint64_t wid = (uint64_t)p;
+
+ printf("Starting PDCP worker %ld\n", wid);
+
+ int retval;
+
+ struct rte_mbuf_batch_ctrl ctrl;
+ struct rte_mbuf pkt;
+ struct rte_mbuf *batch;
+
+ void *work_dequeue[1];
+
+ status[wid].start_time = 0;
+ status[wid].util_time = 0;
+
+ iv_t iv;
+
+ symmetric_key_t sym_key;
+ memset(sym_key, 0 , KEY_SIZE);
+
+
+ char in_fifo_name[32];
+ snprintf(in_fifo_name, 32, "in_fifo_name_%ld", wid);
+ workers[wid].in_fifo = rte_ring_create(in_fifo_name, IN_FIFO_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (NULL == workers[wid].in_fifo){
+ printf("Error creating in_fifo for worker %ld!\n", wid);
+ return -1;
+ }
+
+ char out_fifo_name[32];
+ snprintf(out_fifo_name, 32, "out_fifo_name_%ld", wid);
+ workers[wid].out_fifo = rte_ring_create(out_fifo_name, OUT_FIFO_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (NULL == workers[wid].out_fifo){
+ printf("Error creating out_fifo for worker %ld!\n", wid);
+ return -1;
+ }
+
+ /* Initialise the current return batch to none. */
+ workers[wid].current_return_batch = NULL;
+
+
+
+
+ data_ctx_t data_ctx = (data_ctx_t)wid;
+ sec_ctx_t sec_ctx = nt_crypto_new_security_context(LOOPBACK, sym_key, data_ctx);
+ if(NULL == sec_ctx){
+ printf("Error creating new security context!\n");
+ return -1;
+ }
+
+ while ( !quit_signal ) {
+
+ // status[wid].start_time = rte_rdtsc();
+
+
+ // printf("worker %ld looking for work\n", wid);
+
+ /* Wait for work in the queue. */
+ while (rte_ring_empty(workers[wid].in_fifo)){
+ if ( unlikely(quit_signal) ) return 0;
+ }
+
+ retval = rte_ring_dequeue(workers[wid].in_fifo, work_dequeue);
+ if( unlikely(retval) ){
+ rte_exit(EXIT_FAILURE, "rte_ring_dequeue error\n");
+ }
+ batch = (struct rte_mbuf *)work_dequeue[0];
+
+ // printf("worker %ld found work\n", wid);
+
+ batch->ol_flags |= PKT_BATCH;
+
+ return_batch_s *return_batch = malloc(sizeof(return_batch_s));
+
+ /* Store the mbuf on the fifo, when it returns from libcrypto, it is send back. */
+ return_batch->pkt = batch;
+
+ /* Remove the batch header from the buffer. */
+ rte_pktmbuf_adj(batch, sizeof(struct rte_mbuf_batch_pkt_hdr));
+ batch->batch_size = batch->pkt_len;
+
+ /* Store the data return address on the queue. */
+ while (rte_ring_full(workers[wid].out_fifo)) {
+ if ( unlikely(quit_signal) ){
+ return -1;
+ }
+ }
+ retval = rte_ring_enqueue(workers[wid].out_fifo, return_batch);
+ if( unlikely(0 != retval) ){
+ rte_exit(EXIT_FAILURE, "Error in rte_ring_enqueue into return_addr_fifo\n");
+ }
+
+ data_t data;
+ if (rte_pktmbuf_batch_get_first(batch, &pkt, &ctrl)) {
+ do {
+ // status[wid].data_in += pkt.data_len + 24;
+ status[wid].data_in += pkt.data_len;
+ status[wid].pkts_in++;
+
+ data = rte_pktmbuf_mtod(&pkt, data_t);
+
+ status[wid].start_time = rte_rdtsc();
+
+ /* Copy the ciphertext directly back into the RX mbuf at the same position. */
+ retval = nt_crypto_cipher(sec_ctx, &iv, data, data, pkt.data_len);
+ if( unlikely(retval) ){
+ printf("nt_crypto_cipher did not cipher!?!\n");
+ quit_signal = 1;
+ break;
+ }
+
+ status[wid].util_time += rte_rdtsc() - status[wid].start_time;
+
+ } while (rte_pktmbuf_batch_get_next(batch, &pkt, &ctrl));
+
+ /* Store the (last) data address of the batch => used to determine when a batch has returned. */
+ return_batch->last_address = data;
+
+ } // for each buffer
+ // status[wid].util_time += rte_rdtsc() - status[wid].start_time;
+
+ } // forever
+
+
+ printf("Ending PDCP worker %ld\n", wid);
+ return 0;
+}
+
+volatile uint32_t tx_count = 0;
+volatile uint32_t try_counter = 0;
+
+int dist_worker(void *p) {
+ uint64_t wid = (uint64_t)p;
+
+ printf("Starting DIST worker %ld\n", wid);
+
+ int retval;
+ uint8_t rx_port_id = 0;
+ uint8_t tx_port_id = 0;
+
+ uint8_t queue_id = 0;
+
+ uint8_t current_worker = 0;
+
+ void *tx_pkt_data[1];
+ struct rte_mbuf * tx_batch;
+
+ /* Ensure that all workers has started up! */
+ // sleep(1);
+ usleep(10000);
+
+ while ( !quit_signal ) {
+
+ /* Get burst of RX packets, from first port of pair. */
+ struct rte_mbuf *bufs[RX_BURST_SIZE];
+
+ status[wid].start_time = rte_rdtsc();
+ const uint32_t nb_rx = rte_eth_rx_burst(rx_port_id, queue_id, bufs, RX_BURST_SIZE);
+ if (likely(nb_rx)) {
+
+ uint16_t buf;
+ for (buf = 0; buf < nb_rx; buf++) {
+
+
+ // printf("Enqueue at worker %d\n", current_worker);
+ while (rte_ring_full(workers[current_worker].in_fifo)) {
+ if ( unlikely(quit_signal) ){
+ printf("workers[current_worker].in_fifo is full: %d\n", current_worker);
+ return -1;
+ }
+ }
+ retval = rte_ring_enqueue( workers[current_worker].in_fifo, bufs[buf] );
+ if( unlikely(0 != retval) ){
+ rte_exit(EXIT_FAILURE, "Error in rte_ring_enqueue into return_addr_fifo\n");
+ }
+
+ current_worker = (current_worker + 1) % (worker_count - FIRST_PDCP_CORE);
+
+
+ // status[wid].start_time = rte_rdtsc();
+ // if( !rte_ring_empty(callback_fifo) ){
+
+ // retval = rte_ring_dequeue(callback_fifo, tx_pkt_data);
+ // if( unlikely(retval) ){
+ // rte_exit(EXIT_FAILURE, "rte_ring_dequeue error\n");
+ // }
+ // tx_batch = (struct rte_mbuf *)tx_pkt_data[0];
+
+ // uint16_t nb_tx = 0;
+ // do {
+ // if ( unlikely(quit_signal) ){
+ // return -1;
+ // }
+ // nb_tx = rte_eth_tx_burst(tx_port_id, TX_QUEUE_ID, &tx_batch, 1);
+ // try_counter++;
+ // } while( unlikely(0 == nb_tx) );
+
+ // tx_count++;
+
+ // status[wid].util_time += (rte_rdtsc() - status[wid].start_time);
+ // }
+
+
+ }
+ }
+
+ // status[wid].util_time += rte_rdtsc() - status[wid].start_time;
+ // status[wid].start_time = rte_rdtsc();
+
+ int i;
+ for(i = 0; i < 8; ++i){
+
+ if(rte_ring_empty(callback_fifo) ){
+ break;
+ }
+
+ // printf("dist_worker Tx time!\n");
+
+ // status[wid].pkts_out++;
+
+ retval = rte_ring_dequeue(callback_fifo, tx_pkt_data);
+ if( unlikely(retval) ){
+ rte_exit(EXIT_FAILURE, "rte_ring_dequeue error\n");
+ }
+ tx_batch = (struct rte_mbuf *)tx_pkt_data[0];
+
+
+
+ // status[wid].start_time = rte_rdtsc();
+
+ uint16_t nb_tx = 0;
+ do {
+ if ( unlikely(quit_signal) ){
+ return -1;
+ }
+ nb_tx = rte_eth_tx_burst(tx_port_id, TX_QUEUE_ID, &tx_batch, 1);
+ } while( unlikely(0 == nb_tx) );
+
+ // status[wid].util_time += (rte_rdtsc() - status[wid].start_time);
+ } /*for Tx batch. */
+
+ status[wid].util_time += (rte_rdtsc() - status[wid].start_time);
+
+ } /* Forever */
+
+ printf("Ending DIST worker %ld\n", wid);
+
+ return 0;
+}
+
+
+int main(int argc, char *argv[]) {
+
+ printf("Welcome to PDCP\n");
+
+ uint8_t portid, worker_core, core;
+ quit_signal = 0;
+
+ /* Catch ctrl-c so we can print on exit. */
+ signal(SIGINT, int_handler);
+
+ // srand(4);
+
+ /* Initialize the Environment Abstraction Layer (EAL). */
+ int ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+
+ argc -= ret;
+ argv += ret;
+
+ worker_count = rte_lcore_count();
+ if ( MIN_CORE_COUNT > worker_count ) {
+ printf("\nERROR: Need at least %i cores.\n", MIN_CORE_COUNT);
+ return -1;
+ }
+
+ printf("Launching libcrypto worker on core: %d\n", LIBCRYPT_CORE_ID);
+ ret = nt_crypto_init(callback, LIBCRYPT_CORE_ID);
+ if(ret){
+ printf("Error in nt_crypto_init\n");
+ return -1;
+ }
+
+ ret = init_pdcp();
+
+ // printf("Launching dist_worker worker on core: %d\n", DIST_CORE);
+ rte_eal_remote_launch((lcore_function_t *)dist_worker, (void*)DIST_CORE, DIST_CORE);
+
+ /* Start security contexts from the first free core - after the libcrypto thread. */
+ for (worker_core = FIRST_PDCP_CORE; worker_core < worker_count; ++worker_core) {
+ uint64_t idx = worker_core - FIRST_PDCP_CORE;
+ // printf("Launching PDCP worker on core: %d\n", worker_core);
+ rte_eal_remote_launch((lcore_function_t *)pdcp_worker, (void*)idx, worker_core);
+ // rte_eal_remote_launch((lcore_function_t *)pdcp_worker, (void*)worker_core, worker_core);
+ // usleep(10000);
+ }
+
+ stat_print();
+
+ nt_crypto_end();
+
+
+ RTE_LCORE_FOREACH_SLAVE(core) {
+ if (rte_eal_wait_lcore(core) < 0)
+ return -1;
+ }
+
+ uint8_t nb_ports = rte_eth_dev_count();
+ for (portid = 0; portid < nb_ports; portid++) {
+ printf("Closing port %i\n", portid);
+ rte_eth_dev_stop(portid);
+ rte_eth_dev_close(portid);
+ }
+ return 0;
+}
+
+
+static int stat_print(void) {
+
+ uint64_t total_pkt_out = 0;
+ uint64_t total_pkt_in;
+ uint64_t prev_total_pkt_in = 0;
+
+ uint64_t total_data_in;
+ uint64_t prev_total_data_in = 0;
+
+ uint64_t total_util_time = 0;
+
+ init_time = rte_rdtsc();
+
+ while ( !quit_signal ) {
+ total_pkt_in = 0;
+ total_data_in = 0;
+ total_pkt_out = 0;
+
+ total_util_time = 0;
+
+ uint8_t i;
+ for (i = 0; i < 2; ++i) {
+ total_data_in += status[i].data_in;
+
+ total_pkt_in += status[i].pkts_in;
+ total_pkt_out += status[i].pkts_out;
+
+ total_util_time += status[i].util_time;
+ // printf("status[%d].util_time = %d\n", i , status[i].util_time/1000000000);
+ }
+
+
+ uint64_t byte_per_sec = total_data_in - prev_total_data_in;
+ prev_total_data_in = total_data_in;
+ double mbps = (byte_per_sec * 8 ) / 1000.0 / 1000.0;
+
+
+
+ double mpps = (double)((total_pkt_in - prev_total_pkt_in) / 1000000.0);
+ prev_total_pkt_in = total_pkt_in;
+
+ double util = (double)total_util_time / (double)(rte_rdtsc() - init_time);
+ double dist_util = (double)status[DIST_CORE].util_time / (double)(rte_rdtsc() - init_time);
+
+ // printf("status[DIST_CORE].util_time = %0.2f\n", status[DIST_CORE].util_time / 1000000000.0);
+ // printf("rte_rdtsc() - init_time = %0.2f\n", (rte_rdtsc() - init_time)/1000000000.0 ) ;
+
+ printf("IN: %ld\tOUT: %ld\tinflight: %ld\tbw: %0.0f Mb/s\tmpps: %2.2f\tutil: %2.2f\tdutil: %2.2f\n", total_pkt_in, total_pkt_out, total_pkt_in - total_pkt_out, mbps, mpps, util, dist_util );
+ sleep(1);
+ }
+
+ return 0;
+} \ No newline at end of file