diff options
-rw-r--r-- | AAL/SR-IOV/README | 0 | ||||
-rw-r--r-- | AAL/qat/Makefile | 73 | ||||
-rw-r--r-- | AAL/qat/libcrypto.c | 864 | ||||
-rw-r--r-- | AAL/qat/libcrypto.h | 288 | ||||
-rw-r--r-- | AAL/qat/libcrypto_test.c | 1015 | ||||
-rw-r--r-- | AAL/qat/main.c | 763 | ||||
-rw-r--r-- | AAL/qat/pdcp.c | 660 |
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 = ð->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], ð->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 |