From patchwork Wed Jan 11 20:55:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121843 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id EF12A423AF; Wed, 11 Jan 2023 21:56:20 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id ED0B342D27; Wed, 11 Jan 2023 21:56:14 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 462FF40A7D for ; Wed, 11 Jan 2023 21:56:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470572; x=1705006572; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9x/amUTJyOpEI6l+weL/iz4LOOW3W0iIEblKH9xRKpI=; b=noGFmheAAmJEgJwxPMZUiW8I+sZrzmc31BOqwnj+s/+Ys4iH2fndhzjb XgAqTSYcsUwNzlgBS/nuhPeSTrZhRglZUMghvNN3fpAV4p0ziNopSs7hm 9evnEvr/Bf7z4jfdvz2sd+i56OsT2KGSxjbcaDu3REh31MZa2yry2uFxs 7a2xS00c1AVV7qYlD1JuDDNbskOy6XaaYef+fcuR/TU4QmKUYMoiwYINX dzWeJKeFaip4miRQdK/rB/Ha5Ux1S4VJlnppxBk6nydp04VDRni+B3Zxj OgxnwF2l7zQLWL1ZdSuxrq+zRpzya+xVdnB+0a+8LWmOlHndQjpYctR/w Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229765" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229765" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:11 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518831" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518831" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:10 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 01/11] pipeline: add IPsec support Date: Wed, 11 Jan 2023 20:55:58 +0000 Message-Id: <20230111205608.87953-2-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This block is providing IPsec support to the SWX pipeline. The IPsec block is external to the pipeline, so it needs to be explicitly instantiated and connected to a pipeline through the I/O ports. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- lib/pipeline/meson.build | 4 +- lib/pipeline/rte_swx_ipsec.c | 1851 ++++++++++++++++++++++++++++++++++ lib/pipeline/rte_swx_ipsec.h | 383 +++++++ lib/pipeline/version.map | 9 + 4 files changed, 2246 insertions(+), 1 deletion(-) create mode 100644 lib/pipeline/rte_swx_ipsec.c create mode 100644 lib/pipeline/rte_swx_ipsec.h diff --git a/lib/pipeline/meson.build b/lib/pipeline/meson.build index 3ca98ed194..aa3fd0c2b8 100644 --- a/lib/pipeline/meson.build +++ b/lib/pipeline/meson.build @@ -11,6 +11,7 @@ sources = files( 'rte_pipeline.c', 'rte_port_in_action.c', 'rte_table_action.c', + 'rte_swx_ipsec.c', 'rte_swx_pipeline.c', 'rte_swx_pipeline_spec.c', 'rte_swx_ctl.c', @@ -19,8 +20,9 @@ headers = files( 'rte_pipeline.h', 'rte_port_in_action.h', 'rte_table_action.h', + 'rte_swx_ipsec.h', 'rte_swx_pipeline.h', 'rte_swx_extern.h', 'rte_swx_ctl.h', ) -deps += ['port', 'table', 'meter', 'sched', 'cryptodev'] +deps += ['port', 'table', 'meter', 'sched', 'cryptodev', 'ipsec'] diff --git a/lib/pipeline/rte_swx_ipsec.c b/lib/pipeline/rte_swx_ipsec.c new file mode 100644 index 0000000000..7ad2ee7227 --- /dev/null +++ b/lib/pipeline/rte_swx_ipsec.c @@ -0,0 +1,1851 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rte_swx_ipsec.h" + +#ifndef RTE_SWX_IPSEC_HUGE_PAGES_DISABLE + +#include + +static void * +env_calloc(size_t size, size_t alignment, int numa_node) +{ + return rte_zmalloc_socket(NULL, size, alignment, numa_node); +} + +static void +env_free(void *start, size_t size __rte_unused) +{ + rte_free(start); +} + +#else + +#include + +static void * +env_calloc(size_t size, size_t alignment __rte_unused, int numa_node) +{ + void *start; + + if (numa_available() == -1) + return NULL; + + start = numa_alloc_onnode(size, numa_node); + if (!start) + return NULL; + + memset(start, 0, size); + return start; +} + +static void +env_free(void *start, size_t size) +{ + if ((numa_available() == -1) || !start) + return; + + numa_free(start, size); +} + +#endif + +#ifndef RTE_SWX_IPSEC_POOL_CACHE_SIZE +#define RTE_SWX_IPSEC_POOL_CACHE_SIZE 256 +#endif + +/* The two crypto device mempools have their size set to the number of SAs. The mempool API requires + * the mempool size to be at least 1.5 times the size of the mempool cache. + */ +#define N_SA_MIN (RTE_SWX_IPSEC_POOL_CACHE_SIZE * 1.5) + +struct ipsec_sa { + struct rte_ipsec_session s; + int valid; +}; + +struct ipsec_pkts_in { + struct rte_mbuf *pkts[RTE_SWX_IPSEC_BURST_SIZE_MAX]; + struct ipsec_sa *sa[RTE_SWX_IPSEC_BURST_SIZE_MAX]; + struct rte_ipsec_group groups[RTE_SWX_IPSEC_BURST_SIZE_MAX]; + struct rte_crypto_op *group_cops[RTE_SWX_IPSEC_BURST_SIZE_MAX]; + struct rte_crypto_op *cops[RTE_SWX_IPSEC_BURST_SIZE_MAX]; + uint32_t n_cops; +}; + +struct ipsec_pkts_out { + struct rte_crypto_op *cops[RTE_SWX_IPSEC_BURST_SIZE_MAX]; + struct rte_mbuf *group_pkts[RTE_SWX_IPSEC_BURST_SIZE_MAX]; + struct rte_ipsec_group groups[RTE_SWX_IPSEC_BURST_SIZE_MAX]; + struct rte_mbuf *pkts[RTE_SWX_IPSEC_BURST_SIZE_MAX]; + uint32_t n_pkts; +}; + +struct rte_swx_ipsec { + /* + * Parameters. + */ + + /* IPsec instance name. */ + char name[RTE_SWX_IPSEC_NAME_SIZE]; + + /* Input packet queue. */ + struct rte_ring *ring_in; + + /* Output packet queue. */ + struct rte_ring *ring_out; + + /* Crypto device ID. */ + uint8_t dev_id; + + /* Crypto device queue pair ID. */ + uint16_t qp_id; + + /* Burst sizes. */ + struct rte_swx_ipsec_burst_size bsz; + + /* SA table size. */ + size_t n_sa_max; + + /* + * Internals. + */ + /* Crypto device buffer pool for sessions. */ + struct rte_mempool *mp_session; + + /* Crypto device bufer pool for session private data. */ + struct rte_mempool *mp_session_priv; + + /* Pre-crypto packets. */ + struct ipsec_pkts_in in; + + /* Post-crypto packets. */ + struct ipsec_pkts_out out; + + /* Crypto device enqueue threshold. */ + uint32_t crypto_wr_threshold; + + /* Packets currently under crypto device processing. */ + uint32_t n_pkts_crypto; + + /* List of free SADB positions. */ + uint32_t *sa_free_id; + + /* Number of elements in the SADB list of free positions. */ + size_t n_sa_free_id; + + /* Allocated memory total size in bytes. */ + size_t total_size; + + /* Flag for registration to the global list of instances. */ + int registered; + + /* + * Table memory. + */ + uint8_t memory[] __rte_cache_aligned; +}; + +static inline struct ipsec_sa * +ipsec_sa_get(struct rte_swx_ipsec *ipsec, uint32_t sa_id) +{ + struct ipsec_sa *sadb = (struct ipsec_sa *)ipsec->memory; + + return &sadb[sa_id & (ipsec->n_sa_max - 1)]; +} + +/* Global list of instances. */ +TAILQ_HEAD(rte_swx_ipsec_list, rte_tailq_entry); + +static struct rte_tailq_elem rte_swx_ipsec_tailq = { + .name = "RTE_SWX_IPSEC", +}; + +EAL_REGISTER_TAILQ(rte_swx_ipsec_tailq) + +struct rte_swx_ipsec * +rte_swx_ipsec_find(const char *name) +{ + struct rte_swx_ipsec_list *ipsec_list; + struct rte_tailq_entry *te = NULL; + + if (!name || + !name[0] || + (strnlen(name, RTE_SWX_IPSEC_NAME_SIZE) == RTE_SWX_IPSEC_NAME_SIZE)) + return NULL; + + ipsec_list = RTE_TAILQ_CAST(rte_swx_ipsec_tailq.head, rte_swx_ipsec_list); + + rte_mcfg_tailq_read_lock(); + + TAILQ_FOREACH(te, ipsec_list, next) { + struct rte_swx_ipsec *ipsec = (struct rte_swx_ipsec *)te->data; + + if (!strncmp(name, ipsec->name, sizeof(ipsec->name))) { + rte_mcfg_tailq_read_unlock(); + return ipsec; + } + } + + rte_mcfg_tailq_read_unlock(); + return NULL; +} + +static int +ipsec_register(struct rte_swx_ipsec *ipsec) +{ + struct rte_swx_ipsec_list *ipsec_list; + struct rte_tailq_entry *te = NULL; + + ipsec_list = RTE_TAILQ_CAST(rte_swx_ipsec_tailq.head, rte_swx_ipsec_list); + + rte_mcfg_tailq_write_lock(); + + TAILQ_FOREACH(te, ipsec_list, next) { + struct rte_swx_ipsec *elem = (struct rte_swx_ipsec *)te->data; + + if (!strncmp(ipsec->name, elem->name, sizeof(ipsec->name))) { + rte_mcfg_tailq_write_unlock(); + return -EEXIST; + } + } + + te = calloc(1, sizeof(struct rte_tailq_entry)); + if (!te) { + rte_mcfg_tailq_write_unlock(); + return -ENOMEM; + } + + te->data = (void *)ipsec; + TAILQ_INSERT_TAIL(ipsec_list, te, next); + rte_mcfg_tailq_write_unlock(); + return 0; +} + +static void +ipsec_unregister(struct rte_swx_ipsec *ipsec) +{ + struct rte_swx_ipsec_list *ipsec_list; + struct rte_tailq_entry *te = NULL; + + ipsec_list = RTE_TAILQ_CAST(rte_swx_ipsec_tailq.head, rte_swx_ipsec_list); + + rte_mcfg_tailq_write_lock(); + + TAILQ_FOREACH(te, ipsec_list, next) { + if (te->data == (void *)ipsec) { + TAILQ_REMOVE(ipsec_list, te, next); + rte_mcfg_tailq_write_unlock(); + free(te); + return; + } + } + + rte_mcfg_tailq_write_unlock(); +} + +static void +ipsec_session_free(struct rte_swx_ipsec *ipsec, struct rte_ipsec_session *s); + +void +rte_swx_ipsec_free(struct rte_swx_ipsec *ipsec) +{ + size_t i; + + if (!ipsec) + return; + + /* Remove the current instance from the global list. */ + if (ipsec->registered) + ipsec_unregister(ipsec); + + /* SADB. */ + for (i = 0; i < ipsec->n_sa_max; i++) { + struct ipsec_sa *sa = ipsec_sa_get(ipsec, i); + + if (!sa->valid) + continue; + + /* SA session. */ + ipsec_session_free(ipsec, &sa->s); + } + + /* Crypto device buffer pools. */ + rte_mempool_free(ipsec->mp_session); + rte_mempool_free(ipsec->mp_session_priv); + + /* IPsec object memory. */ + env_free(ipsec, ipsec->total_size); +} + +int +rte_swx_ipsec_create(struct rte_swx_ipsec **ipsec_out, + const char *name, + struct rte_swx_ipsec_params *params, + int numa_node) +{ + char resource_name[RTE_SWX_IPSEC_NAME_SIZE]; + struct rte_swx_ipsec *ipsec = NULL; + struct rte_ring *ring_in, *ring_out; + struct rte_cryptodev_info dev_info; + size_t n_sa_max, sadb_offset, sadb_size, sa_free_id_offset, sa_free_id_size, total_size, i; + int dev_id, status = 0; + + /* Check input parameters. */ + if (!ipsec_out || + !name || + !name[0] || + (strnlen((name), RTE_SWX_IPSEC_NAME_SIZE) == RTE_SWX_IPSEC_NAME_SIZE) || + !params || + (params->bsz.ring_rd > RTE_SWX_IPSEC_BURST_SIZE_MAX) || + (params->bsz.ring_wr > RTE_SWX_IPSEC_BURST_SIZE_MAX) || + (params->bsz.crypto_wr > RTE_SWX_IPSEC_BURST_SIZE_MAX) || + (params->bsz.crypto_rd > RTE_SWX_IPSEC_BURST_SIZE_MAX) || + !params->n_sa_max) { + status = -EINVAL; + goto error; + } + + ring_in = rte_ring_lookup(params->ring_in_name); + if (!ring_in) { + status = -EINVAL; + goto error; + } + + ring_out = rte_ring_lookup(params->ring_out_name); + if (!ring_out) { + status = -EINVAL; + goto error; + } + + dev_id = rte_cryptodev_get_dev_id(params->crypto_dev_name); + if (dev_id == -1) { + status = -EINVAL; + goto error; + } + + rte_cryptodev_info_get(dev_id, &dev_info); + if (params->crypto_dev_queue_pair_id >= dev_info.max_nb_queue_pairs) { + status = -EINVAL; + goto error; + } + + /* Memory allocation. */ + n_sa_max = rte_align64pow2(RTE_MAX(params->n_sa_max, N_SA_MIN)); + + sadb_offset = sizeof(struct rte_swx_ipsec); + sadb_size = RTE_CACHE_LINE_ROUNDUP(n_sa_max * sizeof(struct ipsec_sa)); + + sa_free_id_offset = sadb_offset + sadb_size; + sa_free_id_size = RTE_CACHE_LINE_ROUNDUP(n_sa_max * sizeof(uint32_t)); + + total_size = sa_free_id_offset + sa_free_id_size; + ipsec = env_calloc(total_size, RTE_CACHE_LINE_SIZE, numa_node); + if (!ipsec) { + status = -ENOMEM; + goto error; + } + + /* Initialization. */ + strcpy(ipsec->name, name); + ipsec->ring_in = ring_in; + ipsec->ring_out = ring_out; + ipsec->dev_id = (uint8_t)dev_id; + ipsec->qp_id = params->crypto_dev_queue_pair_id; + memcpy(&ipsec->bsz, ¶ms->bsz, sizeof(struct rte_swx_ipsec_burst_size)); + ipsec->n_sa_max = n_sa_max; + + ipsec->crypto_wr_threshold = params->bsz.crypto_wr * 3 / 4; + + ipsec->sa_free_id = (uint32_t *)&ipsec->memory[sa_free_id_offset]; + for (i = 0; i < n_sa_max; i++) + ipsec->sa_free_id[i] = n_sa_max - 1 - i; + ipsec->n_sa_free_id = n_sa_max; + + ipsec->total_size = total_size; + + /* Crypto device memory pools. */ + snprintf(resource_name, sizeof(resource_name), "%s_mp", name); + ipsec->mp_session = rte_cryptodev_sym_session_pool_create(resource_name, + n_sa_max, /* number of pool elements */ + 0, /* pool element size */ + RTE_SWX_IPSEC_POOL_CACHE_SIZE, /* pool cache size */ + 0, /* pool element private data size */ + numa_node); + if (!ipsec->mp_session) { + status = -ENOMEM; + goto error; + } + + snprintf(resource_name, sizeof(resource_name), "%s_mp_priv", name); + ipsec->mp_session_priv = rte_mempool_create(resource_name, + n_sa_max, /* number of pool elements */ + rte_cryptodev_sym_get_private_session_size(dev_id), /* pool element size */ + RTE_SWX_IPSEC_POOL_CACHE_SIZE, /* pool cache size */ + 0, /* pool private data size */ + NULL, + NULL, + NULL, + NULL, + numa_node, + 0); /* pool flags */ + if (!ipsec->mp_session_priv) { + status = -ENOMEM; + goto error; + } + + /* Add the current instance to the global list. */ + status = ipsec_register(ipsec); + if (status) + goto error; + + ipsec->registered = 1; + + *ipsec_out = ipsec; + return 0; + +error: + rte_swx_ipsec_free(ipsec); + return status; +} + +static inline int +ipsec_sa_group(struct rte_swx_ipsec *ipsec, int n_pkts) +{ + struct ipsec_sa *sa; + struct rte_ipsec_group *g; + int n_groups, n_pkts_in_group, i; + + sa = ipsec->in.sa[0]; + + g = &ipsec->in.groups[0]; + g->id.ptr = sa; + g->m = &ipsec->in.pkts[0]; + n_pkts_in_group = 1; + n_groups = 1; + + for (i = 1; i < n_pkts; i++) { + struct ipsec_sa *sa_new = ipsec->in.sa[i]; + + /* Same SA => Add the current pkt to the same group. */ + if (sa_new == sa) { + n_pkts_in_group++; + continue; + } + + /* Different SA => Close the current group & add the current pkt to a new group. */ + g->cnt = n_pkts_in_group; + sa = sa_new; + + g++; + g->id.ptr = sa; + g->m = &ipsec->in.pkts[i]; + n_pkts_in_group = 1; + n_groups++; + } + + /* Close the last group. */ + g->cnt = n_pkts_in_group; + + return n_groups; +} + +static inline void +ipsec_crypto_enqueue(struct rte_swx_ipsec *ipsec, uint16_t n_cops) +{ + struct rte_crypto_op **dst0 = ipsec->in.cops, **dst; + struct rte_crypto_op **src = ipsec->in.group_cops; + + uint32_t n_pkts_crypto = ipsec->n_pkts_crypto; + uint32_t n_dst = ipsec->in.n_cops; + uint32_t n_dst_max = ipsec->bsz.crypto_wr; + uint32_t n_dst_avail = n_dst_max - n_dst; + uint32_t n_src = n_cops; + uint32_t i; + + dst = &dst0[n_dst]; + + /* Shortcut: If no elements in DST and enough elements in SRC, then simply use SRC directly + * instead of moving the SRC to DST first and then using DST. + */ + if (!n_dst && n_src >= ipsec->crypto_wr_threshold) { + uint16_t n_ok; + + n_ok = rte_cryptodev_enqueue_burst(ipsec->dev_id, ipsec->qp_id, src, n_src); + ipsec->n_pkts_crypto = n_pkts_crypto + n_ok; + + for (i = n_ok; i < n_src; i++) { + struct rte_crypto_op *cop = src[i]; + struct rte_mbuf *m = cop->sym->m_src; + + rte_pktmbuf_free(m); + } + + return; + } + + /* Move from SRC to DST. Every time DST gets full, send burst from DST. */ + for ( ; n_src >= n_dst_avail; ) { + uint32_t n_ok; + + /* Move from SRC to DST. */ + for (i = 0; i < n_dst_avail; i++) + *dst++ = *src++; + + n_src -= n_dst_avail; + + /* DST full: send burst from DST. */ + n_ok = rte_cryptodev_enqueue_burst(ipsec->dev_id, ipsec->qp_id, dst0, n_dst_max); + n_pkts_crypto += n_ok; + + for (i = n_ok ; i < n_dst_max; i++) { + struct rte_crypto_op *cop = dst0[i]; + struct rte_mbuf *m = cop->sym->m_src; + + rte_pktmbuf_free(m); + } + + /* Next iteration. */ + dst = dst0; + n_dst = 0; + n_dst_avail = n_dst_max; + } + + ipsec->n_pkts_crypto = n_pkts_crypto; + + /* Move from SRC to DST. Not enough elements in SRC to get DST full. */ + for (i = 0; i < n_src; i++) + *dst++ = *src++; + + n_dst += n_src; + + ipsec->in.n_cops = n_dst; +} + +/** + * Packet buffer anatomy: + * + * +----------+---------+--------------------------------------------------------------------------+ + * | Offset | Size | Description | + * | (Byte #) | (Bytes) | | + * +==========+=========+==========================================================================+ + * | 0 | 128 | Meta-data: struct rte_mbuf. | + * | | | The buf_addr field points to the start of the packet section. | + * +----------+---------+--------------------------------------------------------------------------+ + * | 128 | 128 | Meta-data: struct ipsec_mbuf (see below). | + * +----------+---------+--------------------------------------------------------------------------+ + * | 256 | | Packet section. | + * | | | The first packet byte is placed at the offset indicated by the struct | + * | | | rte_mbuf::data_off field relative to the start of the packet section. | + * +----------+---------+--------------------------------------------------------------------------+ + */ +struct ipsec_mbuf { + struct ipsec_sa *sa; + struct rte_crypto_op cop; + struct rte_crypto_sym_op sym_cop; + uint8_t buffer[32]; /* The crypto IV is placed here. */ +}; + +/* Offset from the start of the struct ipsec_mbuf::cop where the crypto IV will be placed. */ +#define IV_OFFSET (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op)) + +#define META_LENGTH sizeof(struct rte_swx_ipsec_input_packet_metadata) + +static inline void +rte_swx_ipsec_pre_crypto(struct rte_swx_ipsec *ipsec) +{ + int n_pkts, n_groups, i; + + /* Read packets from the input ring. */ + n_pkts = rte_ring_sc_dequeue_burst(ipsec->ring_in, + (void **)ipsec->in.pkts, + ipsec->bsz.ring_rd, + NULL); + if (!n_pkts) + return; + + /* Get the SA for each packet. */ + for (i = 0; i < n_pkts; i++) { + struct rte_mbuf *m = ipsec->in.pkts[i]; + struct rte_swx_ipsec_input_packet_metadata *meta; + struct rte_ipv4_hdr *ipv4_hdr; + uint32_t sa_id; + + meta = rte_pktmbuf_mtod(m, struct rte_swx_ipsec_input_packet_metadata *); + ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, META_LENGTH); + + /* Read the SA ID from the IPsec meta-data placed at the front of the IP packet. */ + sa_id = ntohl(meta->sa_id); + + /* Consume the IPsec meta-data. */ + m->data_off += META_LENGTH; + m->data_len -= META_LENGTH; + m->pkt_len -= META_LENGTH; + + /* Set the fields required by the IPsec library. */ + m->l2_len = 0; + m->l3_len = (ipv4_hdr->version_ihl >> 4 == 4) ? + sizeof(struct rte_ipv4_hdr) : + sizeof(struct rte_ipv6_hdr); + + /* Get the SA. */ + ipsec->in.sa[i] = ipsec_sa_get(ipsec, sa_id); + } + + /* Group packets that share the same SA. */ + n_groups = ipsec_sa_group(ipsec, n_pkts); + + /* Write each group of packets sharing the same SA to the crypto device. */ + for (i = 0; i < n_groups; i++) { + struct rte_ipsec_group *g = &ipsec->in.groups[i]; + struct ipsec_sa *sa = g->id.ptr; + struct rte_ipsec_session *s = &sa->s; + uint32_t j; + uint16_t n_pkts_ok; + + /* Prepare the crypto ops for the current group. */ + for (j = 0; j < g->cnt; j++) { + struct rte_mbuf *m = g->m[j]; + struct ipsec_mbuf *priv = rte_mbuf_to_priv(m); + + priv->sa = sa; + ipsec->in.group_cops[j] = &priv->cop; + } + + n_pkts_ok = rte_ipsec_pkt_crypto_prepare(s, g->m, ipsec->in.group_cops, g->cnt); + + for (j = n_pkts_ok; j < g->cnt; j++) { + struct rte_mbuf *m = g->m[j]; + + rte_pktmbuf_free(m); + } + + /* Write the crypto ops of the current group to the crypto device. */ + ipsec_crypto_enqueue(ipsec, n_pkts_ok); + } +} + +static inline void +ipsec_ring_enqueue(struct rte_swx_ipsec *ipsec, struct rte_ipsec_group *g, uint32_t n_pkts) +{ + struct rte_mbuf **dst0 = ipsec->out.pkts, **dst; + struct rte_mbuf **src = g->m; + + uint32_t n_dst = ipsec->out.n_pkts; + uint32_t n_dst_max = ipsec->bsz.ring_wr; + uint32_t n_dst_avail = n_dst_max - n_dst; + uint32_t n_src = n_pkts; + uint32_t i; + + dst = &dst0[n_dst]; + + /* Move from SRC to DST. Every time DST gets full, send burst from DST. */ + for ( ; n_src >= n_dst_avail; ) { + uint32_t n_ok; + + /* Move from SRC to DST. */ + for (i = 0; i < n_dst_avail; i++) + *dst++ = *src++; + + n_src -= n_dst_avail; + + /* DST full: send burst from DST. */ + n_ok = rte_ring_sp_enqueue_burst(ipsec->ring_out, (void **)dst0, n_dst_max, NULL); + + for (i = n_ok ; i < n_dst_max; i++) { + struct rte_mbuf *m = dst[i]; + + rte_pktmbuf_free(m); + } + + /* Next iteration. */ + dst = dst0; + n_dst = 0; + n_dst_avail = n_dst_max; + } + + /* Move from SRC to DST. Not enough elements in SRC to get DST full. */ + for (i = 0; i < n_src; i++) + *dst++ = *src++; + + n_dst += n_src; + + ipsec->out.n_pkts = n_dst; +} + +static inline void +rte_swx_ipsec_post_crypto(struct rte_swx_ipsec *ipsec) +{ + uint32_t n_pkts_crypto = ipsec->n_pkts_crypto, n_pkts, n_groups, i; + + /* Read the crypto ops from the crypto device. */ + if (!n_pkts_crypto) + return; + + n_pkts = rte_cryptodev_dequeue_burst(ipsec->dev_id, + ipsec->qp_id, + ipsec->out.cops, + ipsec->bsz.crypto_rd); + if (!n_pkts) + return; + + ipsec->n_pkts_crypto = n_pkts_crypto - n_pkts; + + /* Group packets that share the same SA. */ + n_groups = rte_ipsec_pkt_crypto_group((const struct rte_crypto_op **)(uintptr_t)ipsec->out.cops, + ipsec->out.group_pkts, + ipsec->out.groups, + n_pkts); + + /* Peform post-crypto IPsec processing for each group of packets that share the same SA. + * Write each group of packets to the output ring. + */ + for (i = 0, n_pkts = 0; i < n_groups; i++) { + struct rte_ipsec_group *g = &ipsec->out.groups[i]; + struct rte_ipsec_session *s = g->id.ptr; + uint32_t n_pkts_ok, j; + + /* Perform post-crypto IPsec processing for the current group. */ + n_pkts_ok = rte_ipsec_pkt_process(s, g->m, g->cnt); + + for (j = n_pkts_ok; j < g->cnt; j++) { + struct rte_mbuf *m = g->m[j]; + + rte_pktmbuf_free(m); + } + + /* Write the packets of the current group to the output ring. */ + ipsec_ring_enqueue(ipsec, g, n_pkts_ok); + } +} + +void +rte_swx_ipsec_run(struct rte_swx_ipsec *ipsec) +{ + rte_swx_ipsec_pre_crypto(ipsec); + rte_swx_ipsec_post_crypto(ipsec); +} + +/** + * IPsec Control Plane API + */ +struct cipher_alg { + const char *name; + enum rte_crypto_cipher_algorithm alg; + uint32_t iv_size; + uint32_t block_size; + uint32_t key_size; +}; + +struct auth_alg { + const char *name; + enum rte_crypto_auth_algorithm alg; + uint32_t iv_size; + uint32_t digest_size; + uint32_t key_size; +}; + +struct aead_alg { + const char *name; + enum rte_crypto_aead_algorithm alg; + uint32_t iv_size; + uint32_t block_size; + uint32_t digest_size; + uint32_t key_size; + uint32_t aad_size; +}; + +static struct cipher_alg cipher_algs[] = { + [0] = { + .name = "null", + .alg = RTE_CRYPTO_CIPHER_NULL, + .iv_size = 0, + .block_size = 4, + .key_size = 0, + }, + + [1] = { + .name = "aes-cbc-128", + .alg = RTE_CRYPTO_CIPHER_AES_CBC, + .iv_size = 16, + .block_size = 16, + .key_size = 16, + }, + + [2] = { + .name = "aes-cbc-192", + .alg = RTE_CRYPTO_CIPHER_AES_CBC, + .iv_size = 16, + .block_size = 16, + .key_size = 24, + }, + + [3] = { + .name = "aes-cbc-256", + .alg = RTE_CRYPTO_CIPHER_AES_CBC, + .iv_size = 16, + .block_size = 16, + .key_size = 32, + }, + + [4] = { + .name = "aes-ctr-128", + .alg = RTE_CRYPTO_CIPHER_AES_CTR, + .iv_size = 8, + .block_size = 4, + .key_size = 20, + }, + + [5] = { + .name = "aes-ctr-192", + .alg = RTE_CRYPTO_CIPHER_AES_CTR, + .iv_size = 16, + .block_size = 16, + .key_size = 28, + }, + + [6] = { + .name = "aes-ctr-256", + .alg = RTE_CRYPTO_CIPHER_AES_CTR, + .iv_size = 16, + .block_size = 16, + .key_size = 36, + }, + + [7] = { + .name = "3des-cbc", + .alg = RTE_CRYPTO_CIPHER_3DES_CBC, + .iv_size = 8, + .block_size = 8, + .key_size = 24, + }, + + [8] = { + .name = "des-cbc", + .alg = RTE_CRYPTO_CIPHER_DES_CBC, + .iv_size = 8, + .block_size = 8, + .key_size = 8, + }, +}; + +static struct auth_alg auth_algs[] = { + [0] = { + .name = "null", + .alg = RTE_CRYPTO_AUTH_NULL, + .iv_size = 0, + .digest_size = 0, + .key_size = 0, + }, + + [1] = { + .name = "sha1-hmac", + .alg = RTE_CRYPTO_AUTH_SHA1_HMAC, + .iv_size = 0, + .digest_size = 12, + .key_size = 20, + }, + + [2] = { + .name = "sha256-hmac", + .alg = RTE_CRYPTO_AUTH_SHA256_HMAC, + .iv_size = 0, + .digest_size = 16, + .key_size = 32, + }, + + [3] = { + .name = "sha384-hmac", + .alg = RTE_CRYPTO_AUTH_SHA384_HMAC, + .iv_size = 0, + .digest_size = 24, + .key_size = 48, + }, + + [4] = { + .name = "sha512-hmac", + .alg = RTE_CRYPTO_AUTH_SHA512_HMAC, + .iv_size = 0, + .digest_size = 32, + .key_size = 64, + }, + + [5] = { + .name = "aes-gmac", + .alg = RTE_CRYPTO_AUTH_AES_GMAC, + .iv_size = 8, + .digest_size = 16, + .key_size = 20, + }, + + [6] = { + .name = "aes-xcbc-mac-96", + .alg = RTE_CRYPTO_AUTH_AES_XCBC_MAC, + .iv_size = 0, + .digest_size = 12, + .key_size = 16, + }, +}; + +static struct aead_alg aead_algs[] = { + [0] = { + .name = "aes-gcm-128", + .alg = RTE_CRYPTO_AEAD_AES_GCM, + .iv_size = 8, + .block_size = 4, + .key_size = 20, + .digest_size = 16, + .aad_size = 8, + }, + + [1] = { + .name = "aes-gcm-192", + .alg = RTE_CRYPTO_AEAD_AES_GCM, + .iv_size = 8, + .block_size = 4, + .key_size = 28, + .digest_size = 16, + .aad_size = 8, + }, + + [2] = { + .name = "aes-gcm-256", + .alg = RTE_CRYPTO_AEAD_AES_GCM, + .iv_size = 8, + .block_size = 4, + .key_size = 36, + .digest_size = 16, + .aad_size = 8, + }, + + [3] = { + .name = "aes-ccm-128", + .alg = RTE_CRYPTO_AEAD_AES_CCM, + .iv_size = 8, + .block_size = 4, + .key_size = 20, + .digest_size = 16, + .aad_size = 8, + }, + + [4] = { + .name = "aes-ccm-192", + .alg = RTE_CRYPTO_AEAD_AES_CCM, + .iv_size = 8, + .block_size = 4, + .key_size = 28, + .digest_size = 16, + .aad_size = 8, + }, + + [5] = { + .name = "aes-ccm-256", + .alg = RTE_CRYPTO_AEAD_AES_CCM, + .iv_size = 8, + .block_size = 4, + .key_size = 36, + .digest_size = 16, + .aad_size = 8, + }, + + [6] = { + .name = "chacha20-poly1305", + .alg = RTE_CRYPTO_AEAD_CHACHA20_POLY1305, + .iv_size = 12, + .block_size = 64, + .key_size = 36, + .digest_size = 16, + .aad_size = 8, + }, +}; + +static struct cipher_alg * +cipher_alg_find(const char *name) +{ + size_t i; + + for (i = 0; i < RTE_DIM(cipher_algs); i++) { + struct cipher_alg *alg = &cipher_algs[i]; + + if (!strcmp(name, alg->name)) + return alg; + } + + return NULL; +} + +static struct cipher_alg * +cipher_alg_find_by_id(enum rte_crypto_cipher_algorithm alg_id, uint32_t key_size) +{ + size_t i; + + for (i = 0; i < RTE_DIM(cipher_algs); i++) { + struct cipher_alg *alg = &cipher_algs[i]; + + if (alg->alg == alg_id && alg->key_size == key_size) + return alg; + } + + return NULL; +} + +static struct auth_alg * +auth_alg_find(const char *name) +{ + size_t i; + + for (i = 0; i < RTE_DIM(auth_algs); i++) { + struct auth_alg *alg = &auth_algs[i]; + + if (!strcmp(name, alg->name)) + return alg; + } + + return NULL; +} + +static struct auth_alg * +auth_alg_find_by_id(enum rte_crypto_auth_algorithm alg_id, uint32_t key_size) +{ + size_t i; + + for (i = 0; i < RTE_DIM(auth_algs); i++) { + struct auth_alg *alg = &auth_algs[i]; + + if (alg->alg == alg_id && alg->key_size == key_size) + return alg; + } + + return NULL; +} + +static struct aead_alg * +aead_alg_find(const char *name) +{ + size_t i; + + for (i = 0; i < RTE_DIM(aead_algs); i++) { + struct aead_alg *alg = &aead_algs[i]; + + if (!strcmp(name, alg->name)) + return alg; + } + + return NULL; +} + +static struct aead_alg * +aead_alg_find_by_id(enum rte_crypto_aead_algorithm alg_id, uint32_t key_size) +{ + size_t i; + + for (i = 0; i < RTE_DIM(aead_algs); i++) { + struct aead_alg *alg = &aead_algs[i]; + + if (alg->alg == alg_id && alg->key_size == key_size) + return alg; + } + + return NULL; +} + +static int +char_to_hex(char c, uint8_t *val) +{ + if (c >= '0' && c <= '9') { + *val = c - '0'; + return 0; + } + + if (c >= 'A' && c <= 'F') { + *val = c - 'A' + 10; + return 0; + } + + if (c >= 'a' && c <= 'f') { + *val = c - 'a' + 10; + return 0; + } + + return -EINVAL; +} + +static int +hex_string_parse(char *src, uint8_t *dst, uint32_t n_dst_bytes) +{ + uint32_t i; + + /* Check input arguments. */ + if (!src || !src[0] || !dst || !n_dst_bytes) + return -EINVAL; + + /* Skip any leading "0x" or "0X" in the src string. */ + if ((src[0] == '0') && (src[1] == 'x' || src[1] == 'X')) + src += 2; + + /* Convert each group of two hex characters in the src string to one byte in dst array. */ + for (i = 0; i < n_dst_bytes; i++) { + uint8_t a, b; + int status; + + status = char_to_hex(*src, &a); + if (status) + return status; + src++; + + status = char_to_hex(*src, &b); + if (status) + return status; + src++; + + dst[i] = a * 16 + b; + } + + /* Check for the end of the src string. */ + if (*src) + return -EINVAL; + + return 0; +} + +static int +token_is_comment(const char *token) +{ + if ((token[0] == '#') || + (token[0] == ';') || + ((token[0] == '/') && (token[1] == '/'))) + return 1; /* TRUE. */ + + return 0; /* FALSE. */ +} + +#define MAX_TOKENS 64 + +#define CHECK(condition, msg) \ +do { \ + if (!(condition)) { \ + if (errmsg) \ + *errmsg = msg; \ + goto error; \ + } \ +} while (0) + +struct rte_swx_ipsec_sa_params * +rte_swx_ipsec_sa_read(struct rte_swx_ipsec *ipsec __rte_unused, + const char *string, + int *is_blank_or_comment, + const char **errmsg) +{ + char *token_array[MAX_TOKENS], **t; + struct rte_swx_ipsec_sa_params *p = NULL; + char *s0 = NULL, *s; + uint32_t n_tokens = 0; + int blank_or_comment = 0; + + /* Check input arguments. */ + CHECK(string && string[0], "NULL input"); + + /* Memory allocation. */ + s0 = strdup(string); + p = calloc(1, sizeof(struct rte_swx_ipsec_sa_params)); + CHECK(s0 && p, "Not enough memory"); + + /* Parse the string into tokens. */ + for (s = s0; ; ) { + char *token; + + token = strtok_r(s, " \f\n\r\t\v", &s); + if (!token || token_is_comment(token)) + break; + + CHECK(n_tokens < RTE_DIM(token_array), "Too many tokens"); + + token_array[n_tokens] = token; + n_tokens++; + } + + t = token_array; + if (!n_tokens) { + blank_or_comment = 1; + goto error; + } + + /* + * Crypto operation. + */ + if (!strcmp(t[0], "encrypt")) + p->encrypt = 1; + else if (!strcmp(t[0], "decrypt")) + p->encrypt = 0; + else + CHECK(0, "Missing \"encrypt\"/\"decrypt\" keyword"); + + t++; + n_tokens--; + + /* + * Crypto parameters. + */ + CHECK(n_tokens >= 2, "Not enough tokens"); + + if (!strcmp(t[0], "cipher")) { + struct cipher_alg *cipher_alg; + struct auth_alg *auth_alg; + uint32_t key_size; + + p->crypto.is_aead = 0; + + /* cipher. */ + cipher_alg = cipher_alg_find(t[1]); + CHECK(cipher_alg, "Unsupported cipher algorithm"); + + key_size = cipher_alg->key_size; + p->crypto.cipher_auth.cipher.alg = cipher_alg->alg; + p->crypto.cipher_auth.cipher.key_size = key_size; + + t += 2; + n_tokens -= 2; + + if (key_size) { + int status; + + CHECK(n_tokens >= 2, "Not enough tokens"); + CHECK(!strcmp(t[0], "key"), "Missing cipher \"key\" keyword"); + CHECK(key_size <= RTE_DIM(p->crypto.cipher_auth.cipher.key), + "Cipher algorithm key too big"); + + status = hex_string_parse(t[1], p->crypto.cipher_auth.cipher.key, key_size); + CHECK(!status, "Cipher key invalid format"); + + t += 2; + n_tokens -= 2; + } + + /* authentication. */ + CHECK(n_tokens >= 2, "Not enough tokens"); + CHECK(!strcmp(t[0], "auth"), "Missing \"auth\" keyword"); + + auth_alg = auth_alg_find(t[1]); + CHECK(auth_alg, "Unsupported authentication algorithm"); + + key_size = auth_alg->key_size; + p->crypto.cipher_auth.auth.alg = auth_alg->alg; + p->crypto.cipher_auth.auth.key_size = key_size; + + t += 2; + n_tokens -= 2; + + if (key_size) { + int status; + + CHECK(n_tokens >= 2, "Not enough tokens"); + CHECK(!strcmp(t[0], "key"), "Missing authentication \"key\" keyword"); + CHECK(key_size <= RTE_DIM(p->crypto.cipher_auth.auth.key), + "Authentication algorithm key too big"); + + status = hex_string_parse(t[1], p->crypto.cipher_auth.auth.key, key_size); + CHECK(!status, "Authentication key invalid format"); + + t += 2; + n_tokens -= 2; + } + } else if (!strcmp(t[0], "aead")) { + struct aead_alg *alg; + uint32_t key_size; + int status; + + p->crypto.is_aead = 1; + + CHECK(n_tokens >= 4, "Not enough tokens"); + alg = aead_alg_find(t[1]); + CHECK(alg, "Unsupported AEAD algorithm"); + + key_size = alg->key_size; + p->crypto.aead.alg = alg->alg; + p->crypto.aead.key_size = key_size; + + CHECK(!strcmp(t[2], "key"), "Missing AEAD \"key\" keyword"); + CHECK(key_size <= RTE_DIM(p->crypto.aead.key), + "AEAD algorithm key too big"); + + status = hex_string_parse(t[3], p->crypto.aead.key, key_size); + CHECK(!status, "AEAD key invalid format"); + + t += 4; + n_tokens -= 4; + } else + CHECK(0, "Missing \"cipher\"/\"aead\" keyword"); + + /* + * Packet ecapsulation parameters. + */ + CHECK(n_tokens >= 4, "Not enough tokens"); + CHECK(!strcmp(t[0], "esp"), "Missing \"esp\" keyword"); + CHECK(!strcmp(t[1], "spi"), "Missing \"spi\" keyword"); + + p->encap.esp.spi = strtoul(t[2], &t[2], 0); + CHECK(!t[2][0], "ESP SPI field invalid format"); + + t += 3; + n_tokens -= 3; + + if (!strcmp(t[0], "tunnel")) { + p->encap.tunnel_mode = 1; + + CHECK(n_tokens >= 6, "Not enough tokens"); + + if (!strcmp(t[1], "ipv4")) { + uint32_t addr; + + p->encap.tunnel_ipv4 = 1; + + CHECK(!strcmp(t[2], "srcaddr"), "Missing \"srcaddr\" keyword"); + + addr = strtoul(t[3], &t[3], 0); + CHECK(!t[3][0], "Tunnel IPv4 source address invalid format"); + p->encap.tunnel.ipv4.src_addr.s_addr = htonl(addr); + + CHECK(!strcmp(t[4], "dstaddr"), "Missing \"dstaddr\" keyword"); + + addr = strtoul(t[5], &t[5], 0); + CHECK(!t[5][0], "Tunnel IPv4 destination address invalid format"); + p->encap.tunnel.ipv4.dst_addr.s_addr = htonl(addr); + + t += 6; + n_tokens -= 6; + } else if (!strcmp(t[1], "ipv6")) { + int status; + + p->encap.tunnel_ipv4 = 0; + + CHECK(!strcmp(t[2], "srcaddr"), "Missing \"srcaddr\" keyword"); + + status = hex_string_parse(t[3], + p->encap.tunnel.ipv6.src_addr.s6_addr, + 16); + CHECK(!status, "Tunnel IPv6 source address invalid format"); + + CHECK(!strcmp(t[4], "dstaddr"), "Missing \"dstaddr\" keyword"); + + status = hex_string_parse(t[5], + p->encap.tunnel.ipv6.dst_addr.s6_addr, + 16); + CHECK(!status, "Tunnel IPv6 destination address invalid format"); + + t += 6; + n_tokens -= 6; + } else + CHECK(0, "Missing \"ipv4\"/\"ipv6\" keyword"); + } else if (!strcmp(t[0], "transport")) { + p->encap.tunnel_mode = 0; + + t++; + n_tokens--; + } else + CHECK(0, "Missing \"tunnel\"/\"transport\" keyword"); + + /* + * Any other parameters. + */ + CHECK(!n_tokens, "Unexpected trailing tokens"); + + free(s0); + return p; + +error: + free(p); + free(s0); + if (is_blank_or_comment) + *is_blank_or_comment = blank_or_comment; + return NULL; +} + +static void +tunnel_ipv4_header_set(struct rte_ipv4_hdr *h, struct rte_swx_ipsec_sa_params *p) +{ + struct rte_ipv4_hdr ipv4_hdr = { + .version_ihl = 0x45, + .type_of_service = 0, + .total_length = 0, /* Cannot be pre-computed. */ + .packet_id = 0, + .fragment_offset = 0, + .time_to_live = 64, + .next_proto_id = IPPROTO_ESP, + .hdr_checksum = 0, /* Cannot be pre-computed. */ + .src_addr = p->encap.tunnel.ipv4.src_addr.s_addr, + .dst_addr = p->encap.tunnel.ipv4.dst_addr.s_addr, + }; + + memcpy(h, &ipv4_hdr, sizeof(ipv4_hdr)); +} + +static void +tunnel_ipv6_header_set(struct rte_ipv6_hdr *h, struct rte_swx_ipsec_sa_params *p) +{ + struct rte_ipv6_hdr ipv6_hdr = { + .vtc_flow = 0x60000000, + .payload_len = 0, /* Cannot be pre-computed. */ + .proto = IPPROTO_ESP, + .hop_limits = 64, + .src_addr = {0}, + .dst_addr = {0}, + }; + + memcpy(h, &ipv6_hdr, sizeof(ipv6_hdr)); + memcpy(h->src_addr, p->encap.tunnel.ipv6.src_addr.s6_addr, 16); + memcpy(h->dst_addr, p->encap.tunnel.ipv6.dst_addr.s6_addr, 16); +} + +/* IPsec library SA parameters. */ +static struct rte_crypto_sym_xform * +crypto_xform_get(struct rte_swx_ipsec_sa_params *p, + struct rte_crypto_sym_xform *xform, + uint32_t *salt_out) +{ + if (p->crypto.is_aead) { + struct aead_alg *alg; + uint32_t key_size, salt, iv_length; + + alg = aead_alg_find_by_id(p->crypto.aead.alg, p->crypto.aead.key_size); + if (!alg) + return NULL; + + /* salt and salt-related key size adjustment. */ + key_size = p->crypto.aead.key_size - 4; + memcpy(&salt, &p->crypto.aead.key[key_size], 4); + + /* IV length. */ + iv_length = 12; + if (p->crypto.aead.alg == RTE_CRYPTO_AEAD_AES_CCM) + iv_length = 11 ; + + /* xform. */ + xform[0].type = RTE_CRYPTO_SYM_XFORM_AEAD; + xform[0].aead.op = p->encrypt ? + RTE_CRYPTO_AEAD_OP_ENCRYPT : + RTE_CRYPTO_AEAD_OP_DECRYPT; + xform[0].aead.algo = p->crypto.aead.alg; + xform[0].aead.key.data = p->crypto.aead.key; + xform[0].aead.key.length = key_size; + xform[0].aead.iv.offset = IV_OFFSET; + xform[0].aead.iv.length = iv_length; + xform[0].aead.digest_length = alg->digest_size; + xform[0].aead.aad_length = alg->aad_size; + xform[0].next = NULL; + + *salt_out = salt; + return &xform[0]; + } else { + struct cipher_alg *cipher_alg; + struct auth_alg *auth_alg; + uint32_t cipher_key_size, auth_key_size, salt, auth_iv_length; + + cipher_alg = cipher_alg_find_by_id(p->crypto.cipher_auth.cipher.alg, + p->crypto.cipher_auth.cipher.key_size); + if (!cipher_alg) + return NULL; + + auth_alg = auth_alg_find_by_id(p->crypto.cipher_auth.auth.alg, + p->crypto.cipher_auth.auth.key_size); + if (!auth_alg) + return NULL; + + /* salt and salt-related key size adjustment. */ + cipher_key_size = p->crypto.cipher_auth.cipher.key_size; + auth_key_size = p->crypto.cipher_auth.auth.key_size; + + switch (p->crypto.cipher_auth.cipher.alg) { + case RTE_CRYPTO_CIPHER_AES_CBC: + case RTE_CRYPTO_CIPHER_3DES_CBC: + salt = (uint32_t)rand(); + break; + + case RTE_CRYPTO_CIPHER_AES_CTR: + cipher_key_size -= 4; + memcpy(&salt, &p->crypto.cipher_auth.cipher.key[cipher_key_size], 4); + break; + + default: + salt = 0; + } + + if (p->crypto.cipher_auth.auth.alg == RTE_CRYPTO_AUTH_AES_GMAC) { + auth_key_size -= 4; + memcpy(&salt, &p->crypto.cipher_auth.auth.key[auth_key_size], 4); + } + + /* IV length. */ + auth_iv_length = cipher_alg->iv_size; + if (p->crypto.cipher_auth.auth.alg == RTE_CRYPTO_AUTH_AES_GMAC) + auth_iv_length = 12; + + /* xform. */ + if (p->encrypt) { + xform[0].type = RTE_CRYPTO_SYM_XFORM_CIPHER; + xform[0].cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; + xform[0].cipher.algo = p->crypto.cipher_auth.cipher.alg; + xform[0].cipher.key.data = p->crypto.cipher_auth.cipher.key; + xform[0].cipher.key.length = cipher_key_size; + xform[0].cipher.iv.offset = IV_OFFSET; + xform[0].cipher.iv.length = cipher_alg->iv_size; + xform[0].cipher.dataunit_len = 0; + xform[0].next = &xform[1]; + + xform[1].type = RTE_CRYPTO_SYM_XFORM_AUTH; + xform[1].auth.op = RTE_CRYPTO_AUTH_OP_GENERATE; + xform[1].auth.algo = p->crypto.cipher_auth.auth.alg; + xform[1].auth.key.data = p->crypto.cipher_auth.auth.key; + xform[1].auth.key.length = auth_key_size; + xform[1].auth.iv.offset = IV_OFFSET; + xform[1].auth.iv.length = auth_iv_length; + xform[1].auth.digest_length = auth_alg->digest_size; + xform[1].next = NULL; + } else { + xform[0].type = RTE_CRYPTO_SYM_XFORM_AUTH; + xform[0].auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; + xform[0].auth.algo = p->crypto.cipher_auth.auth.alg; + xform[0].auth.key.data = p->crypto.cipher_auth.auth.key; + xform[0].auth.key.length = auth_key_size; + xform[0].auth.iv.offset = IV_OFFSET; + xform[0].auth.iv.length = auth_iv_length; + xform[0].auth.digest_length = auth_alg->digest_size; + xform[0].next = &xform[1]; + + xform[1].type = RTE_CRYPTO_SYM_XFORM_CIPHER; + xform[1].cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT; + xform[1].cipher.algo = p->crypto.cipher_auth.cipher.alg; + xform[1].cipher.key.data = p->crypto.cipher_auth.cipher.key; + xform[1].cipher.key.length = cipher_key_size; + xform[1].cipher.iv.offset = IV_OFFSET; + xform[1].cipher.iv.length = cipher_alg->iv_size; + xform[1].cipher.dataunit_len = 0; + xform[1].next = NULL; + } + + *salt_out = salt; + + if (p->crypto.cipher_auth.auth.alg == RTE_CRYPTO_AUTH_AES_GMAC) { + if (p->encrypt) + return &xform[1]; + + xform[0].next = NULL; + return &xform[0]; + } + + return &xform[0]; + } +} + +static void +ipsec_xform_get(struct rte_swx_ipsec_sa_params *p, + struct rte_security_ipsec_xform *ipsec_xform, + uint32_t salt) +{ + ipsec_xform->spi = p->encap.esp.spi; + + ipsec_xform->salt = salt; + + ipsec_xform->options.esn = 0; + ipsec_xform->options.udp_encap = 0; + ipsec_xform->options.copy_dscp = 1; + ipsec_xform->options.copy_flabel = 0; + ipsec_xform->options.copy_df = 0; + ipsec_xform->options.dec_ttl = 0; + ipsec_xform->options.ecn = 1; + ipsec_xform->options.stats = 0; + ipsec_xform->options.iv_gen_disable = 0; + ipsec_xform->options.tunnel_hdr_verify = 0; + ipsec_xform->options.udp_ports_verify = 0; + ipsec_xform->options.ip_csum_enable = 0; + ipsec_xform->options.l4_csum_enable = 0; + ipsec_xform->options.ip_reassembly_en = 0; + ipsec_xform->options.reserved_opts = 0; + + ipsec_xform->direction = p->encrypt ? + RTE_SECURITY_IPSEC_SA_DIR_EGRESS : + RTE_SECURITY_IPSEC_SA_DIR_INGRESS; + + ipsec_xform->proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP; + + ipsec_xform->mode = p->encap.tunnel_mode ? + RTE_SECURITY_IPSEC_SA_MODE_TUNNEL : + RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT; + + ipsec_xform->tunnel.type = p->encap.tunnel_ipv4 ? + RTE_SECURITY_IPSEC_TUNNEL_IPV4 : + RTE_SECURITY_IPSEC_TUNNEL_IPV6; + + if (p->encap.tunnel_mode) { + if (p->encap.tunnel_ipv4) { + ipsec_xform->tunnel.ipv4.src_ip = p->encap.tunnel.ipv4.src_addr; + ipsec_xform->tunnel.ipv4.dst_ip = p->encap.tunnel.ipv4.dst_addr; + ipsec_xform->tunnel.ipv4.dscp = 0; + ipsec_xform->tunnel.ipv4.df = 0; + ipsec_xform->tunnel.ipv4.ttl = 64; + } else { + ipsec_xform->tunnel.ipv6.src_addr = p->encap.tunnel.ipv6.src_addr; + ipsec_xform->tunnel.ipv6.dst_addr = p->encap.tunnel.ipv6.dst_addr; + ipsec_xform->tunnel.ipv6.dscp = 0; + ipsec_xform->tunnel.ipv6.flabel = 0; + ipsec_xform->tunnel.ipv6.hlimit = 64; + } + } + + ipsec_xform->life.packets_soft_limit = 0; + ipsec_xform->life.bytes_soft_limit = 0; + ipsec_xform->life.packets_hard_limit = 0; + ipsec_xform->life.bytes_hard_limit = 0; + + ipsec_xform->replay_win_sz = 0; + + ipsec_xform->esn.value = 0; + + ipsec_xform->udp.dport = 0; + ipsec_xform->udp.sport = 0; +} + +static int +ipsec_sa_prm_get(struct rte_swx_ipsec_sa_params *p, + struct rte_ipsec_sa_prm *sa_prm, + struct rte_ipv4_hdr *ipv4_hdr, + struct rte_ipv6_hdr *ipv6_hdr, + struct rte_crypto_sym_xform *crypto_xform) +{ + uint32_t salt; + + memset(sa_prm, 0, sizeof(*sa_prm)); /* Better to be safe than sorry. */ + + sa_prm->userdata = 0; /* Not used. */ + + sa_prm->flags = 0; /* Flag RTE_IPSEC_SAFLAG_SQN_ATOM not enabled. */ + + /* + * crypto_xform. + */ + sa_prm->crypto_xform = crypto_xform_get(p, crypto_xform, &salt); + if (!sa_prm->crypto_xform) + return -EINVAL; + + /* + * ipsec_xform. + */ + ipsec_xform_get(p, &sa_prm->ipsec_xform, salt); + + /* + * tunnel / transport. + * + * Currently, the input IP packet type is assumed to be IPv4. To support both IPv4 and IPv6, + * the input packet type should be added to the SA configuration parameters. + */ + if (p->encap.tunnel_mode) { + if (p->encap.tunnel_ipv4) { + sa_prm->tun.hdr_len = sizeof(struct rte_ipv4_hdr); + sa_prm->tun.hdr_l3_off = 0; + sa_prm->tun.next_proto = IPPROTO_IPIP; /* Assume input IP packet type as IPv4. */ + sa_prm->tun.hdr = ipv4_hdr; + } else { + sa_prm->tun.hdr_len = sizeof(struct rte_ipv6_hdr); + sa_prm->tun.hdr_l3_off = 0; + sa_prm->tun.next_proto = IPPROTO_IPIP; /* Assume input IP packet type as IPv4. */ + sa_prm->tun.hdr = ipv6_hdr; + } + } else { + sa_prm->trs.proto = IPPROTO_IPIP; /* Assume input IP packet type as IPv4. */ + } + + return 0; +} + +static int +ipsec_session_create(struct rte_swx_ipsec *ipsec, + struct rte_swx_ipsec_sa_params *p, + struct rte_ipsec_session *s) +{ + struct rte_ipv4_hdr ipv4_hdr; + struct rte_ipv6_hdr ipv6_hdr; + struct rte_crypto_sym_xform crypto_xform[2]; + struct rte_ipsec_sa_prm sa_prm; + struct rte_ipsec_sa *sa = NULL; + struct rte_cryptodev_sym_session *crypto_session = NULL; + int sa_size; + int sa_valid = 0, crypto_session_valid = 0, status = 0; + + tunnel_ipv4_header_set(&ipv4_hdr, p); + tunnel_ipv6_header_set(&ipv6_hdr, p); + + /* IPsec library SA setup. */ + status = ipsec_sa_prm_get(p, &sa_prm, &ipv4_hdr, &ipv6_hdr, crypto_xform); + if (status) + goto error; + + sa_size = rte_ipsec_sa_size(&sa_prm); + if (sa_size < 0) { + status = sa_size; + goto error; + } + if (!sa_size) { + status = -EINVAL; + goto error; + } + + sa = calloc(1, sa_size); + if (!sa) { + status = -ENOMEM; + goto error; + } + + sa_size = rte_ipsec_sa_init(sa, &sa_prm, sa_size); + if (sa_size < 0) { + status = sa_size; + goto error; + } + if (!sa_size) { + status = -EINVAL; + goto error; + } + + sa_valid = 1; + + /* Cryptodev library session setup. */ + crypto_session = rte_cryptodev_sym_session_create(ipsec->mp_session); + if (!crypto_session) { + status = -ENOMEM; + goto error; + } + + status = rte_cryptodev_sym_session_init(ipsec->dev_id, + crypto_session, + sa_prm.crypto_xform, + ipsec->mp_session_priv); + if (status) + goto error; + + crypto_session_valid = 1; + + /* IPsec library session setup. */ + s->sa = sa; + s->type = RTE_SECURITY_ACTION_TYPE_NONE; + s->crypto.ses = crypto_session; + s->crypto.dev_id = ipsec->dev_id; + s->pkt_func.prepare.async = NULL; + s->pkt_func.process = NULL; + + return rte_ipsec_session_prepare(s); + +error: + /* sa. */ + if (sa_valid) + rte_ipsec_sa_fini(sa); + + free(sa); + + /* crypto_session. */ + if (crypto_session_valid) + rte_cryptodev_sym_session_clear(ipsec->dev_id, crypto_session); + + if (crypto_session) + rte_cryptodev_sym_session_free(crypto_session); + + /* s. */ + memset(s, 0, sizeof(*s)); + + return status; +} + +static void +ipsec_session_free(struct rte_swx_ipsec *ipsec, + struct rte_ipsec_session *s) +{ + if (!s) + return; + + /* IPsec library SA. */ + if (s->sa) + rte_ipsec_sa_fini(s->sa); + free(s->sa); + + /* Cryptodev library session. */ + if (s->crypto.ses) { + rte_cryptodev_sym_session_clear(ipsec->dev_id, s->crypto.ses); + rte_cryptodev_sym_session_free(s->crypto.ses); + } + + /* IPsec library session. */ + memset(s, 0, sizeof(*s)); +} + +int +rte_swx_ipsec_sa_add(struct rte_swx_ipsec *ipsec, + struct rte_swx_ipsec_sa_params *sa_params, + uint32_t *id) +{ + struct ipsec_sa *sa; + uint32_t sa_id; + int status; + + /* Check the input parameters. */ + if (!ipsec || !sa_params || !id) + return -EINVAL; + + /* Allocate a free SADB entry. */ + if (!ipsec->n_sa_free_id) + return -ENOSPC; + + sa_id = ipsec->sa_free_id[ipsec->n_sa_free_id - 1]; + ipsec->n_sa_free_id--; + + /* Aquire the SA resources. */ + sa = ipsec_sa_get(ipsec, sa_id); + + status = ipsec_session_create(ipsec, sa_params, &sa->s); + if (status) { + /* Free the allocated SADB entry. */ + ipsec->sa_free_id[ipsec->n_sa_free_id] = sa_id; + ipsec->n_sa_free_id++; + + return status; + } + + /* Validate the new SA. */ + sa->valid = 1; + *id = sa_id; + + return 0; +} + +void +rte_swx_ipsec_sa_delete(struct rte_swx_ipsec *ipsec, + uint32_t sa_id) +{ + struct ipsec_sa *sa; + + /* Check the input parameters. */ + if (!ipsec || (sa_id >= ipsec->n_sa_max)) + return; + + /* Release the SA resources. */ + sa = ipsec_sa_get(ipsec, sa_id); + + ipsec_session_free(ipsec, &sa->s); + + /* Free the SADB entry. */ + ipsec->sa_free_id[ipsec->n_sa_free_id] = sa_id; + ipsec->n_sa_free_id++; + + /* Invalidate the SA. */ + sa->valid = 0; +} diff --git a/lib/pipeline/rte_swx_ipsec.h b/lib/pipeline/rte_swx_ipsec.h new file mode 100644 index 0000000000..c2c638a5d7 --- /dev/null +++ b/lib/pipeline/rte_swx_ipsec.h @@ -0,0 +1,383 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ +#ifndef __INCLUDE_RTE_SWX_IPSEC_H__ +#define __INCLUDE_RTE_SWX_IPSEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * RTE SWX Internet Protocol Security (IPsec) + * + * This block is used to provide IPsec support to the SWX pipeline. The block is external to the + * pipeline, hence it needs to be explicitly instantiated by the user and connected to a pipeline + * instance using the pipeline I/O ports. + * + * Main features: + * - IPsec inbound (encrypted input packets -> clear text output packets) and outbound (clear text + * input packets -> encrypted output packets) processing support for tunnel and transport modes. + * + * Security Association (SA): + * - Each IPsec block instance has its own set of SAs used to process the input packets. Each SA is + * identified by its unique SA ID. The IPsec inbound and outbound SAs share the same ID space. + * - Each input packet is first mapped to one of the existing SAs by using the SA ID and then + * processed according to the identified SA. The SA ID is read from input packet. The SA ID field + * is typically written by the pipeline before sending the packet to the IPsec block. + * + * Packet format: + * - IPsec block input packet (i.e. pipeline output packet): + * - IPsec block meta-data header: @see struct rte_swx_ipsec_input_packet_metadata. + * - IPv4 header. + * - IPv4 payload: on the inbound path, it includes the encrypted ESP packet. + * - IPsec block output packet (i.e. pipeline input packet): + * - IPv4 header. + * - IPv4 payload: on the outbound path, it includes the encrypted ESP packet. + * + * SA update procedure: + * - To add a new SA, @see function rte_swx_ipsec_sa_add(). + * - To delete an existing SA, @see function rte_swx_ipsec_sa_delete(). + * - To update an existing SA, the control plane has to follow the following steps: + * 1. Add a new SA with potentially a different set of configuration parameters. This step can + * fail, for example when the SA table is full. + * 2. Wait until no more packets are using the old SA. + * 3. Delete the old SA. + */ + +#include +#include +#include + +#include +#include + +/** + * IPsec Setup API + */ + +/** IPsec instance opaque data structure. */ +struct rte_swx_ipsec; + +/** Name size. */ +#ifndef RTE_SWX_IPSEC_NAME_SIZE +#define RTE_SWX_IPSEC_NAME_SIZE 64 +#endif + +/** Maximum burst size. */ +#ifndef RTE_SWX_IPSEC_BURST_SIZE_MAX +#define RTE_SWX_IPSEC_BURST_SIZE_MAX 256 +#endif + +/** IPsec burst sizes. */ +struct rte_swx_ipsec_burst_size { + /** Input ring read burst size. */ + uint32_t ring_rd; + + /** Output ring write burst size. */ + uint32_t ring_wr; + + /** Crypto device request queue write burst size. */ + uint32_t crypto_wr; + + /** Crypto device response queue read burst size. */ + uint32_t crypto_rd; +}; + +/** + * IPsec instance configuration parameters + * + */ +struct rte_swx_ipsec_params { + /** Input packet queue. */ + const char *ring_in_name; + + /** Output packet queue. */ + const char *ring_out_name; + + /** Crypto device name. */ + const char *crypto_dev_name; + + /** Crypto device queue pair ID. */ + uint32_t crypto_dev_queue_pair_id; + + /** Burst size. */ + struct rte_swx_ipsec_burst_size bsz; + + /** Maximum number of SAs. */ + uint32_t n_sa_max; +}; + +/** + * IPsec input packet meta-data + * + */ +struct rte_swx_ipsec_input_packet_metadata { + /* SA ID. */ + uint32_t sa_id; +}; + +/** + * IPsec instance find + * + * @param[in] name + * IPsec instance name. + * @return + * Valid IPsec instance handle if found or NULL otherwise. + */ +__rte_experimental +struct rte_swx_ipsec * +rte_swx_ipsec_find(const char *name); + +/** + * IPsec instance create + * + * @param[out] ipsec + * IPsec instance handle. Must point to valid memory. Contains valid pipeline handle once this + * function returns successfully. + * @param[in] name + * IPsec instance unique name. + * @param[in] params + * IPsec instance configuration parameters. + * @param[in] numa_node + * Non-Uniform Memory Access (NUMA) node. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument; + * -ENOMEM: Not enough space/cannot allocate memory; + * -EEXIST: Pipeline with this name already exists. + */ +__rte_experimental +int +rte_swx_ipsec_create(struct rte_swx_ipsec **ipsec, + const char *name, + struct rte_swx_ipsec_params *params, + int numa_node); + +/** + * IPsec instance free + * + * @param[in] ipsec + * IPsec instance handle. + */ +__rte_experimental +void +rte_swx_ipsec_free(struct rte_swx_ipsec *ipsec); + +/** + * IPsec Data Plane API + */ + +/** + * IPsec instance run + * + * @param[in] ipsec + * IPsec instance handle. + */ +__rte_experimental +void +rte_swx_ipsec_run(struct rte_swx_ipsec *ipsec); + +/* + * IPsec Control Plane API + */ + +/** Maximum key size in bytes. */ +#define RTE_SWX_IPSEC_KEY_SIZE_MAX 64 + +/** IPsec SA crypto cipher parameters. */ +struct rte_swx_ipsec_sa_cipher_params { + /** Cipher algorithm. */ + enum rte_crypto_cipher_algorithm alg; + + /** Cipher key. */ + uint8_t key[RTE_SWX_IPSEC_KEY_SIZE_MAX]; + + /** Cipher key size in bytes. */ + uint32_t key_size; +}; + +/** IPsec SA crypto authentication parameters. */ +struct rte_swx_ipsec_sa_authentication_params { + /** Authentication algorithm. */ + enum rte_crypto_auth_algorithm alg; + + /** Authentication key. */ + uint8_t key[RTE_SWX_IPSEC_KEY_SIZE_MAX]; + + /** Authentication key size in bytes. */ + uint32_t key_size; +}; + +/** IPsec SA crypto Authenticated Encryption with Associated Data (AEAD) parameters. */ +struct rte_swx_ipsec_sa_aead_params { + /** AEAD algorithm. */ + enum rte_crypto_aead_algorithm alg; + + /** AEAD key. */ + uint8_t key[RTE_SWX_IPSEC_KEY_SIZE_MAX]; + + /** AEAD key size in bytes. */ + uint32_t key_size; +}; + +/** IPsec protocol encapsulation parameters. */ +struct rte_swx_ipsec_sa_encap_params { + /** Encapsulating Security Payload (ESP) header. */ + struct { + /** Security Parameters Index (SPI) field. */ + uint32_t spi; + } esp; + + /** Tunnel mode when non-zero, transport mode when zero. */ + int tunnel_mode; + + /** Tunnel type: Non-zero for IPv4, zero for IPv6. Valid for tunnel mode only. */ + int tunnel_ipv4; + + /** Tunnel parameters. Valid for tunnel mode only. */ + union { + /** IPv4 header. */ + struct { + /** Source address. */ + struct in_addr src_addr; + + /** Destination address. */ + struct in_addr dst_addr; + } ipv4; + + /** IPv6 header. */ + struct { + /** Source address. */ + struct in6_addr src_addr; + + /** Destination address. */ + struct in6_addr dst_addr; + } ipv6; + } tunnel; +}; + +/** IPsec Security Association (SA) parameters. */ +struct rte_swx_ipsec_sa_params { + /** Crypto operation: encrypt when non-zero, decrypt when zero. */ + int encrypt; + + /** Crypto operation parameters. */ + struct { + RTE_STD_C11 + union { + struct { + /** Crypto cipher operation parameters. */ + struct rte_swx_ipsec_sa_cipher_params cipher; + + /** Crypto authentication operation parameters. */ + struct rte_swx_ipsec_sa_authentication_params auth; + } cipher_auth; + + /** Crypto AEAD operation parameters. */ + struct rte_swx_ipsec_sa_aead_params aead; + }; + + /** Non-zero for AEAD, zero for cipher & authentication. */ + int is_aead; + } crypto; + + /** Packet encasulation parameters. */ + struct rte_swx_ipsec_sa_encap_params encap; +}; + +/** + * IPsec SA add + * + * @param[in] ipsec + * IPsec instance handle. + * @param[in] sa_params + * SA parameters. + * @params[out] sa_id. + * On success, the SA ID. + * @return + * 0 on success or error code otherwise. + */ +__rte_experimental +int +rte_swx_ipsec_sa_add(struct rte_swx_ipsec *ipsec, + struct rte_swx_ipsec_sa_params *sa_params, + uint32_t *sa_id); + +/** + * IPsec SA delete + * + * It is the responibility of the Control Plane to make sure the SA to be deleted is no longer used + * by the Data Plane. + * + * @param[in] ipsec + * IPsec instance handle. + * @params[in] sa_id. + * The SA ID. + */ +__rte_experimental +void +rte_swx_ipsec_sa_delete(struct rte_swx_ipsec *ipsec, + uint32_t sa_id); + +/** + * IPsec SA read from string + * + * IPsec SA syntax: + * + * + * : encrypt + * | decrypt + * ; + * + * + * : + * | + * ; + * + * + * : cipher key + * | cipher + * ; + * + * + * : auth key + * | auth + * ; + * + * + * : aead key + * ; + * + * + * : esp spi tunnel ipv4 srcaddr dstaddr + * | esp spi tunnel ipv6 srcaddr dstaddr + * | esp spi transport + * ; + * + * @param[in] ipsec + * IPsec instance handle. + * @param[in] string + * String containing the SA. + * @param[inout] is_blank_or_comment + * On error, when its input value is not NULL, this argument is set to a non-zero value when + * *string* contains a blank or comment line and to zero otherwise. + * @param[inout] errmsg + * On error, when its input value is not NULL, this argument points to a string with details on + * the detected error. + * @return + * Pointer to valid IPsec SA parameters data structure on success or NULL on error. + */ +__rte_experimental +struct rte_swx_ipsec_sa_params * +rte_swx_ipsec_sa_read(struct rte_swx_ipsec *ipsec, + const char *string, + int *is_blank_or_comment, + const char **errmsg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map index 184f45a6b7..58e34459c3 100644 --- a/lib/pipeline/version.map +++ b/lib/pipeline/version.map @@ -155,4 +155,13 @@ EXPERIMENTAL { rte_swx_pipeline_build_from_lib; rte_swx_pipeline_codegen; rte_swx_pipeline_find; + + #added in 23.03 + rte_swx_ipsec_create; + rte_swx_ipsec_find; + rte_swx_ipsec_free; + rte_swx_ipsec_run; + rte_swx_ipsec_sa_add; + rte_swx_ipsec_sa_delete; + rte_swx_ipsec_sa_read; }; From patchwork Wed Jan 11 20:55:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121844 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2B4CB423AF; Wed, 11 Jan 2023 21:56:30 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 625E442D3E; Wed, 11 Jan 2023 21:56:17 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id B1AA142D33 for ; Wed, 11 Jan 2023 21:56:13 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470573; x=1705006573; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JeIxI2EX7t0uaqwuydCObieL88k6xd9M4KVJ6JqHd/g=; b=U3jADPJtA6CpkrCiy9QV/4JnWS3neGXmjikE02YtsECnlQ5vd/N7lQ2+ MquGJT+CXKXNmOAsRBZhYw+BDJwN/IsrcUAiY2kzyckQEsjBLxSk3O6IQ I9LBga3WIQuRlV28KEia/Ec24m4C/KmQQR2Dv5OqEkEH2vBivjcE+oFTF mT26PemSrjiU6afNYsXXcl3aPa5SWTPrH2/E/Yx5lqp0t0L76aB5EJYOt kTwGkdA8fYRejF8U1ECFynkYBo/nofTpz3qw3AcYM+DrZOQ0h0NZCLAS1 MYVh5MQbEgc44C3m6ZB4sBqi7qz2jLB9XbASjzHyC5nG2fkuqGk8FYxcw A==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229769" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229769" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:12 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518837" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518837" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:11 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 02/11] examples/pipeline: rework memory pool support Date: Wed, 11 Jan 2023 20:55:59 +0000 Message-Id: <20230111205608.87953-3-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Rework the memory pool CLI command to accommodate the MBUF private meta-data area size parameter. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/cli.c | 72 ++++++++++------- examples/pipeline/examples/fib.cli | 2 +- examples/pipeline/examples/hash_func.cli | 2 +- examples/pipeline/examples/l2fwd.cli | 2 +- examples/pipeline/examples/l2fwd_macswp.cli | 2 +- .../pipeline/examples/l2fwd_macswp_pcap.cli | 2 +- examples/pipeline/examples/l2fwd_pcap.cli | 2 +- examples/pipeline/examples/learner.cli | 2 +- examples/pipeline/examples/meter.cli | 2 +- examples/pipeline/examples/mirroring.cli | 2 +- examples/pipeline/examples/recirculation.cli | 2 +- examples/pipeline/examples/registers.cli | 2 +- examples/pipeline/examples/selector.cli | 2 +- examples/pipeline/examples/varbit.cli | 2 +- examples/pipeline/examples/vxlan.cli | 2 +- examples/pipeline/examples/vxlan_pcap.cli | 2 +- examples/pipeline/obj.c | 80 +------------------ examples/pipeline/obj.h | 27 ------- 18 files changed, 63 insertions(+), 146 deletions(-) diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c index 8013541c4b..c014598cf1 100644 --- a/examples/pipeline/cli.c +++ b/examples/pipeline/cli.c @@ -192,72 +192,88 @@ parse_table_entry(struct rte_swx_ctl_pipeline *p, } static const char cmd_mempool_help[] = -"mempool \n" -" buffer \n" -" pool \n" -" cache \n" -" cpu \n"; +"mempool " +"meta " +"pkt " +"pool " +"cache " +"numa \n"; static void cmd_mempool(char **tokens, - uint32_t n_tokens, - char *out, - size_t out_size, - void *obj) + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj __rte_unused) { - struct mempool_params p; - char *name; - struct mempool *mempool; + struct rte_mempool *mp; + char *mempool_name; + uint32_t mbuf_private_size, pkt_buffer_size, pool_size, cache_size, numa_node; - if (n_tokens != 10) { + if (n_tokens != 12) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } - name = tokens[1]; + mempool_name = tokens[1]; + + if (strcmp(tokens[2], "meta")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meta"); + return; + } - if (strcmp(tokens[2], "buffer") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); + if (parser_read_uint32(&mbuf_private_size, tokens[3])) { + snprintf(out, out_size, MSG_ARG_INVALID, "mbuf_private_size"); return; } - if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); + if (strcmp(tokens[4], "pkt")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkt"); return; } - if (strcmp(tokens[4], "pool") != 0) { + if (parser_read_uint32(&pkt_buffer_size, tokens[5])) { + snprintf(out, out_size, MSG_ARG_INVALID, "pkt_buffer_size"); + return; + } + + if (strcmp(tokens[6], "pool")) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); return; } - if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) { + if (parser_read_uint32(&pool_size, tokens[7])) { snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); return; } - if (strcmp(tokens[6], "cache") != 0) { + if (strcmp(tokens[8], "cache")) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); return; } - if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) { + if (parser_read_uint32(&cache_size, tokens[9])) { snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); return; } - if (strcmp(tokens[8], "cpu") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); + if (strcmp(tokens[10], "numa")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa"); return; } - if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); + if (parser_read_uint32(&numa_node, tokens[11])) { + snprintf(out, out_size, MSG_ARG_INVALID, "numa_node"); return; } - mempool = mempool_create(obj, name, &p); - if (mempool == NULL) { + mp = rte_pktmbuf_pool_create(mempool_name, + pool_size, + cache_size, + mbuf_private_size, + pkt_buffer_size, + numa_node); + if (!mp) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); return; } diff --git a/examples/pipeline/examples/fib.cli b/examples/pipeline/examples/fib.cli index 4e30c1320f..2450dc9ca4 100644 --- a/examples/pipeline/examples/fib.cli +++ b/examples/pipeline/examples/fib.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/fib.c /tmp/fib.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/hash_func.cli b/examples/pipeline/examples/hash_func.cli index b2e219e4c9..3840e47a2b 100644 --- a/examples/pipeline/examples/hash_func.cli +++ b/examples/pipeline/examples/hash_func.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/hash_func.c /tmp/hash_func.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/l2fwd.cli b/examples/pipeline/examples/l2fwd.cli index 27e37021b9..c5505df296 100644 --- a/examples/pipeline/examples/l2fwd.cli +++ b/examples/pipeline/examples/l2fwd.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/l2fwd_macswp.cli b/examples/pipeline/examples/l2fwd_macswp.cli index 11bb4543b9..bd700707f5 100644 --- a/examples/pipeline/examples/l2fwd_macswp.cli +++ b/examples/pipeline/examples/l2fwd_macswp.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/l2fwd_macswp_pcap.cli b/examples/pipeline/examples/l2fwd_macswp_pcap.cli index 8724dae3b0..aa64b32ab2 100644 --- a/examples/pipeline/examples/l2fwd_macswp_pcap.cli +++ b/examples/pipeline/examples/l2fwd_macswp_pcap.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ; ; List of pipelines. diff --git a/examples/pipeline/examples/l2fwd_pcap.cli b/examples/pipeline/examples/l2fwd_pcap.cli index 4db0a0dc56..619d17474f 100644 --- a/examples/pipeline/examples/l2fwd_pcap.cli +++ b/examples/pipeline/examples/l2fwd_pcap.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ; ; List of pipelines. diff --git a/examples/pipeline/examples/learner.cli b/examples/pipeline/examples/learner.cli index 6c8aa3921e..42184be1c8 100644 --- a/examples/pipeline/examples/learner.cli +++ b/examples/pipeline/examples/learner.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/learner.c /tmp/learner.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/meter.cli b/examples/pipeline/examples/meter.cli index 21582554b9..0fa38b16b8 100644 --- a/examples/pipeline/examples/meter.cli +++ b/examples/pipeline/examples/meter.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/meter.c /tmp/meter.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/mirroring.cli b/examples/pipeline/examples/mirroring.cli index 1d439e04d3..e7391de74b 100644 --- a/examples/pipeline/examples/mirroring.cli +++ b/examples/pipeline/examples/mirroring.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/mirroring.c /tmp/mirroring.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/recirculation.cli b/examples/pipeline/examples/recirculation.cli index 52d0894f12..965c870fd4 100644 --- a/examples/pipeline/examples/recirculation.cli +++ b/examples/pipeline/examples/recirculation.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/recirculation.c /tmp/recirculation.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/registers.cli b/examples/pipeline/examples/registers.cli index 3516f76a5b..aa775f71e5 100644 --- a/examples/pipeline/examples/registers.cli +++ b/examples/pipeline/examples/registers.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/registers.c /tmp/registers.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/selector.cli b/examples/pipeline/examples/selector.cli index f0e251b657..f0608de184 100644 --- a/examples/pipeline/examples/selector.cli +++ b/examples/pipeline/examples/selector.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/selector.c /tmp/selector.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/varbit.cli b/examples/pipeline/examples/varbit.cli index 0f89990471..648b8882c3 100644 --- a/examples/pipeline/examples/varbit.cli +++ b/examples/pipeline/examples/varbit.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/varbit.c /tmp/varbit.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/vxlan.cli b/examples/pipeline/examples/vxlan.cli index 1fbd1be6e4..4565adfaea 100644 --- a/examples/pipeline/examples/vxlan.cli +++ b/examples/pipeline/examples/vxlan.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on diff --git a/examples/pipeline/examples/vxlan_pcap.cli b/examples/pipeline/examples/vxlan_pcap.cli index adc7f73312..510c2ad870 100644 --- a/examples/pipeline/examples/vxlan_pcap.cli +++ b/examples/pipeline/examples/vxlan_pcap.cli @@ -18,7 +18,7 @@ pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so ; ; Note: Customize the parameters below to match your setup. ; -mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 +mempool MEMPOOL0 meta 0 pkt 2176 pool 32K cache 256 numa 0 ; ; List of pipelines. diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c index b7e2316eec..4aaec02d9c 100644 --- a/examples/pipeline/obj.c +++ b/examples/pipeline/obj.c @@ -13,18 +13,12 @@ #include #include -#include #include #include #include #include "obj.h" -/* - * mempool - */ -TAILQ_HEAD(mempool_list, mempool); - /* * link */ @@ -39,75 +33,10 @@ TAILQ_HEAD(ring_list, ring); * obj */ struct obj { - struct mempool_list mempool_list; struct link_list link_list; struct ring_list ring_list; }; -/* - * mempool - */ -#define BUFFER_SIZE_MIN (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) - -struct mempool * -mempool_create(struct obj *obj, const char *name, struct mempool_params *params) -{ - struct mempool *mempool; - struct rte_mempool *m; - - /* Check input params */ - if ((name == NULL) || - mempool_find(obj, name) || - (params == NULL) || - (params->buffer_size < BUFFER_SIZE_MIN) || - (params->pool_size == 0)) - return NULL; - - /* Resource create */ - m = rte_pktmbuf_pool_create( - name, - params->pool_size, - params->cache_size, - 0, - params->buffer_size - sizeof(struct rte_mbuf), - params->cpu_id); - - if (m == NULL) - return NULL; - - /* Node allocation */ - mempool = calloc(1, sizeof(struct mempool)); - if (mempool == NULL) { - rte_mempool_free(m); - return NULL; - } - - /* Node fill in */ - strlcpy(mempool->name, name, sizeof(mempool->name)); - mempool->m = m; - mempool->buffer_size = params->buffer_size; - - /* Node add to list */ - TAILQ_INSERT_TAIL(&obj->mempool_list, mempool, node); - - return mempool; -} - -struct mempool * -mempool_find(struct obj *obj, const char *name) -{ - struct mempool *mempool; - - if (!obj || !name) - return NULL; - - TAILQ_FOREACH(mempool, &obj->mempool_list, node) - if (strcmp(mempool->name, name) == 0) - return mempool; - - return NULL; -} - /* * link */ @@ -172,7 +101,7 @@ link_create(struct obj *obj, const char *name, struct link_params *params) struct rte_eth_conf port_conf; struct link *link; struct link_params_rss *rss; - struct mempool *mempool; + struct rte_mempool *mempool; uint32_t cpu_id, i; int status; uint16_t port_id = 0; @@ -194,8 +123,8 @@ link_create(struct obj *obj, const char *name, struct link_params *params) if (rte_eth_dev_info_get(port_id, &port_info) != 0) return NULL; - mempool = mempool_find(obj, params->rx.mempool_name); - if (mempool == NULL) + mempool = rte_mempool_lookup(params->rx.mempool_name); + if (!mempool) return NULL; rss = params->rx.rss; @@ -252,7 +181,7 @@ link_create(struct obj *obj, const char *name, struct link_params *params) params->rx.queue_size, cpu_id, NULL, - mempool->m); + mempool); if (status < 0) return NULL; @@ -422,7 +351,6 @@ obj_init(void) if (!obj) return NULL; - TAILQ_INIT(&obj->mempool_list); TAILQ_INIT(&obj->link_list); TAILQ_INIT(&obj->ring_list); diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h index 8ea1c414c2..4ea610ceed 100644 --- a/examples/pipeline/obj.h +++ b/examples/pipeline/obj.h @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -24,32 +23,6 @@ struct obj; struct obj * obj_init(void); -/* - * mempool - */ -struct mempool_params { - uint32_t buffer_size; - uint32_t pool_size; - uint32_t cache_size; - uint32_t cpu_id; -}; - -struct mempool { - TAILQ_ENTRY(mempool) node; - char name[NAME_SIZE]; - struct rte_mempool *m; - uint32_t buffer_size; -}; - -struct mempool * -mempool_create(struct obj *obj, - const char *name, - struct mempool_params *params); - -struct mempool * -mempool_find(struct obj *obj, - const char *name); - /* * link */ From patchwork Wed Jan 11 20:56:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121845 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id B0587423AF; Wed, 11 Jan 2023 21:56:36 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 508D242D41; Wed, 11 Jan 2023 21:56:18 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 663D842D33 for ; Wed, 11 Jan 2023 21:56:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470574; x=1705006574; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/FJpuDdFs3Msf3e3Tzpcl8LC06xZ9o6cjfxKebEolsM=; b=W31FiUXQEDvDe4Gb6TCsS17oprbaHzSYbkntz3OfyBpYyk1DEaIChFua ZPktXEELcyoIiTp8/ZQUVoKU3tE5cltdzL5CwChYvmbAC6Y5qF+Kqk+IZ K6mE8hXC2/ohZYZKsHH9Qeiteb3O33LbpBeCHXfNM+PNfxXQOqYB60dlA dLr9tzKED1s9YDRkbGxCZTbB2br/BPnQ69RAlwpw/HKZKoImkECHhB86E A/GJLPTVK/aopsLUnwD475nX5mNeLBlO3zzR3rg9fdrod8XIe+Rf/lqT5 DxAdgcG390kzXay3vQZq8Vg61OJ0Hq1h8FtGKekk6XcIMRvjfcmfk7M8U g==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229776" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229776" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:13 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518849" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518849" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:12 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 03/11] examples/pipeline: streamline ring support Date: Wed, 11 Jan 2023 20:56:00 +0000 Message-Id: <20230111205608.87953-4-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Remove redundant ring related code. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/cli.c | 24 ++++++++++------ examples/pipeline/obj.c | 63 ----------------------------------------- examples/pipeline/obj.h | 21 -------------- 3 files changed, 15 insertions(+), 93 deletions(-) diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c index c014598cf1..471dfbad38 100644 --- a/examples/pipeline/cli.c +++ b/examples/pipeline/cli.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -491,11 +492,11 @@ cmd_ring(char **tokens, uint32_t n_tokens, char *out, size_t out_size, - void *obj) + void *obj __rte_unused) { - struct ring_params p; + struct rte_ring *r; char *name; - struct ring *ring; + uint32_t size, numa_node; if (n_tokens != 6) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); @@ -504,28 +505,32 @@ cmd_ring(char **tokens, name = tokens[1]; - if (strcmp(tokens[2], "size") != 0) { + if (strcmp(tokens[2], "size")) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); return; } - if (parser_read_uint32(&p.size, tokens[3]) != 0) { + if (parser_read_uint32(&size, tokens[3])) { snprintf(out, out_size, MSG_ARG_INVALID, "size"); return; } - if (strcmp(tokens[4], "numa") != 0) { + if (strcmp(tokens[4], "numa")) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa"); return; } - if (parser_read_uint32(&p.numa_node, tokens[5]) != 0) { + if (parser_read_uint32(&numa_node, tokens[5])) { snprintf(out, out_size, MSG_ARG_INVALID, "numa_node"); return; } - ring = ring_create(obj, name, &p); - if (!ring) { + r = rte_ring_create( + name, + size, + (int)numa_node, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (!r) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); return; } @@ -2998,6 +3003,7 @@ cmd_help(char **tokens, "List of commands:\n" "\tmempool\n" "\tethdev\n" + "\tring\n" "\tpipeline codegen\n" "\tpipeline libbuild\n" "\tpipeline build\n" diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c index 4aaec02d9c..f1a50133f4 100644 --- a/examples/pipeline/obj.c +++ b/examples/pipeline/obj.c @@ -24,17 +24,11 @@ */ TAILQ_HEAD(link_list, link); -/* - * ring - */ -TAILQ_HEAD(ring_list, ring); - /* * obj */ struct obj { struct link_list link_list; - struct ring_list ring_list; }; /* @@ -283,62 +277,6 @@ link_next(struct obj *obj, struct link *link) TAILQ_FIRST(&obj->link_list) : TAILQ_NEXT(link, node); } -/* - * ring - */ -struct ring * -ring_create(struct obj *obj, const char *name, struct ring_params *params) -{ - struct ring *ring; - struct rte_ring *r; - unsigned int flags = RING_F_SP_ENQ | RING_F_SC_DEQ; - - /* Check input params */ - if (!name || ring_find(obj, name) || !params || !params->size) - return NULL; - - /** - * Resource create - */ - r = rte_ring_create( - name, - params->size, - params->numa_node, - flags); - if (!r) - return NULL; - - /* Node allocation */ - ring = calloc(1, sizeof(struct ring)); - if (!ring) { - rte_ring_free(r); - return NULL; - } - - /* Node fill in */ - strlcpy(ring->name, name, sizeof(ring->name)); - - /* Node add to list */ - TAILQ_INSERT_TAIL(&obj->ring_list, ring, node); - - return ring; -} - -struct ring * -ring_find(struct obj *obj, const char *name) -{ - struct ring *ring; - - if (!obj || !name) - return NULL; - - TAILQ_FOREACH(ring, &obj->ring_list, node) - if (strcmp(ring->name, name) == 0) - return ring; - - return NULL; -} - /* * obj */ @@ -352,7 +290,6 @@ obj_init(void) return NULL; TAILQ_INIT(&obj->link_list); - TAILQ_INIT(&obj->ring_list); return obj; } diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h index 4ea610ceed..dbbc6d39a0 100644 --- a/examples/pipeline/obj.h +++ b/examples/pipeline/obj.h @@ -73,25 +73,4 @@ link_find(struct obj *obj, const char *name); struct link * link_next(struct obj *obj, struct link *link); -/* - * ring - */ -struct ring_params { - uint32_t size; - uint32_t numa_node; -}; - -struct ring { - TAILQ_ENTRY(ring) node; - char name[NAME_SIZE]; -}; - -struct ring * -ring_create(struct obj *obj, - const char *name, - struct ring_params *params); - -struct ring * -ring_find(struct obj *obj, const char *name); - #endif /* _INCLUDE_OBJ_H_ */ From patchwork Wed Jan 11 20:56:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121846 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id DD945423AF; Wed, 11 Jan 2023 21:56:42 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4383042D46; Wed, 11 Jan 2023 21:56:19 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 10B5B42D3B for ; Wed, 11 Jan 2023 21:56:15 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470576; x=1705006576; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ugyVU28+pHoNS9r3m3VT6hS2M1DTfYubW939xagePf0=; b=DzG6LQsVnTR3+++3y4yX+My4C+50XuAFruW/QxCOGAqv3MkpHvkP0SvZ mQB+5kFMDuV/LSDKtllPXCTP4ayW/ElmvQ1/f/HxZS44njQB+mp758cTL i/NbeSfRtd9M3gTFYE68E3ZSaMwBSUzkO4iXiKIi8/Gvd356kdPCYFz5h xhduuWlg7W3AnN6GN14WqEFX1s05tpafMHY2lgOXyWP8tYdJGN0qqFXG5 ZeZfwO0R/3oNNr1mm40bjij4rMiaKOGAfvinG+YRUz5epQHR6i3bxVS4s o/OZMK4m+oFpiYfNNFuebJzxjmYqa2zExiMUt8UM8T0E2cj9IiPWRRDOG A==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229781" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229781" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:15 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518855" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518855" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:14 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 04/11] examples/pipeline: streamline the Ethernet device support Date: Wed, 11 Jan 2023 20:56:01 +0000 Message-Id: <20230111205608.87953-5-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Streamline the Ethernet device support code and remove redundant code. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/cli.c | 175 ++++++++++++++++++------------------ examples/pipeline/main.c | 12 +-- examples/pipeline/obj.c | 186 +++++++++------------------------------ examples/pipeline/obj.h | 51 ++--------- 4 files changed, 136 insertions(+), 288 deletions(-) diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c index 471dfbad38..37fc6f9551 100644 --- a/examples/pipeline/cli.c +++ b/examples/pipeline/cli.c @@ -292,16 +292,14 @@ cmd_ethdev(char **tokens, uint32_t n_tokens, char *out, size_t out_size, - void *obj) + void *obj __rte_unused) { - struct link_params p; - struct link_params_rss rss; - struct link *link; + struct ethdev_params p = {0}; + struct ethdev_params_rss rss = {0}; char *name; + int status; - memset(&p, 0, sizeof(p)); - - if ((n_tokens < 11) || (n_tokens > 12 + LINK_RXQ_RSS_MAX)) { + if (n_tokens < 11 || n_tokens > 12 + ETHDEV_RXQ_RSS_MAX) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -377,111 +375,98 @@ cmd_ethdev(char **tokens, } } - link = link_create(obj, name, &p); - if (link == NULL) { + status = ethdev_config(name, &p); + if (status) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); return; } } -/* Print the link stats and info */ static void -print_link_info(struct link *link, char *out, size_t out_size) +ethdev_show(uint16_t port_id, char **out, size_t *out_size) { - struct rte_eth_stats stats; - struct rte_ether_addr mac_addr; - struct rte_eth_link eth_link; - uint16_t mtu; - int ret; - - memset(&stats, 0, sizeof(stats)); - rte_eth_stats_get(link->port_id, &stats); - - ret = rte_eth_macaddr_get(link->port_id, &mac_addr); - if (ret != 0) { - snprintf(out, out_size, "\n%s: MAC address get failed: %s", - link->name, rte_strerror(-ret)); - return; - } - - ret = rte_eth_link_get(link->port_id, ð_link); - if (ret < 0) { - snprintf(out, out_size, "\n%s: link get failed: %s", - link->name, rte_strerror(-ret)); - return; - } - - rte_eth_dev_get_mtu(link->port_id, &mtu); - - snprintf(out, out_size, - "\n" - "%s: flags=<%s> mtu %u\n" - "\tether " RTE_ETHER_ADDR_PRT_FMT " rxqueues %u txqueues %u\n" - "\tport# %u speed %s\n" - "\tRX packets %" PRIu64" bytes %" PRIu64"\n" - "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" - "\tTX packets %" PRIu64" bytes %" PRIu64"\n" - "\tTX errors %" PRIu64"\n", - link->name, - eth_link.link_status == 0 ? "DOWN" : "UP", - mtu, - RTE_ETHER_ADDR_BYTES(&mac_addr), - link->n_rxq, - link->n_txq, - link->port_id, - rte_eth_link_speed_to_str(eth_link.link_speed), - stats.ipackets, - stats.ibytes, - stats.ierrors, - stats.imissed, - stats.rx_nombuf, - stats.opackets, - stats.obytes, - stats.oerrors); + char name[RTE_ETH_NAME_MAX_LEN] = {0}; + struct rte_eth_dev_info info = {0}; + struct rte_eth_stats stats = {0}; + struct rte_ether_addr addr = {0}; + struct rte_eth_link link = {0}; + uint32_t length; + uint16_t mtu = 0; + + if (!rte_eth_dev_is_valid_port(port_id)) + return; + + rte_eth_dev_get_name_by_port(port_id, name); + rte_eth_dev_info_get(port_id, &info); + rte_eth_stats_get(port_id, &stats); + rte_eth_macaddr_get(port_id, &addr); + rte_eth_link_get(port_id, &link); + rte_eth_dev_get_mtu(port_id, &mtu); + + snprintf(*out, *out_size, + "%s: flags=<%s> mtu %u\n" + "\tether " RTE_ETHER_ADDR_PRT_FMT " rxqueues %u txqueues %u\n" + "\tport# %u speed %s\n" + "\tRX packets %" PRIu64" bytes %" PRIu64"\n" + "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" + "\tTX packets %" PRIu64" bytes %" PRIu64"\n" + "\tTX errors %" PRIu64"\n\n", + name, + link.link_status ? "UP" : "DOWN", + mtu, + RTE_ETHER_ADDR_BYTES(&addr), + info.nb_rx_queues, + info.nb_tx_queues, + port_id, + rte_eth_link_speed_to_str(link.link_speed), + stats.ipackets, + stats.ibytes, + stats.ierrors, + stats.imissed, + stats.rx_nombuf, + stats.opackets, + stats.obytes, + stats.oerrors); + + length = strlen(*out); + *out_size -= length; + *out += length; } -/* - * ethdev show [] - */ + +static char cmd_ethdev_show_help[] = +"ethdev show [ ]\n"; + static void cmd_ethdev_show(char **tokens, uint32_t n_tokens, char *out, size_t out_size, - void *obj) + void *obj __rte_unused) { - struct link *link; - char *link_name; + uint16_t port_id; if (n_tokens != 2 && n_tokens != 3) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } - if (n_tokens == 2) { - link = link_next(obj, NULL); - - while (link != NULL) { - out_size = out_size - strlen(out); - out = &out[strlen(out)]; - - print_link_info(link, out, out_size); - link = link_next(obj, link); - } - } else { - out_size = out_size - strlen(out); - out = &out[strlen(out)]; + /* Single device. */ + if (n_tokens == 3) { + int status; - link_name = tokens[2]; - link = link_find(obj, link_name); + status = rte_eth_dev_get_port_by_name(tokens[2], &port_id); + if (status) + snprintf(out, out_size, "Error: Invalid Ethernet device name.\n"); - if (link == NULL) { - snprintf(out, out_size, MSG_ARG_INVALID, - "Link does not exist"); - return; - } - print_link_info(link, out, out_size); + ethdev_show(port_id, &out, &out_size); + return; } + + /* All devices. */ + for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) + if (rte_eth_dev_is_valid_port(port_id)) + ethdev_show(port_id, &out, &out_size); } static const char cmd_ring_help[] = @@ -3003,6 +2988,7 @@ cmd_help(char **tokens, "List of commands:\n" "\tmempool\n" "\tethdev\n" + "\tethdev show\n" "\tring\n" "\tpipeline codegen\n" "\tpipeline libbuild\n" @@ -3038,9 +3024,16 @@ cmd_help(char **tokens, return; } - if (strcmp(tokens[0], "ethdev") == 0) { - snprintf(out, out_size, "\n%s\n", cmd_ethdev_help); - return; + if (!strcmp(tokens[0], "ethdev")) { + if (n_tokens == 1) { + snprintf(out, out_size, "\n%s\n", cmd_ethdev_help); + return; + } + + if (n_tokens == 2 && !strcmp(tokens[1], "show")) { + snprintf(out, out_size, "\n%s\n", cmd_ethdev_show_help); + return; + } } if (strcmp(tokens[0], "ring") == 0) { diff --git a/examples/pipeline/main.c b/examples/pipeline/main.c index 6fb839f4cb..da5dd2b3f6 100644 --- a/examples/pipeline/main.c +++ b/examples/pipeline/main.c @@ -135,7 +135,6 @@ int main(int argc, char **argv) { struct conn *conn; - struct obj *obj; int status; /* Parse application arguments */ @@ -150,13 +149,6 @@ main(int argc, char **argv) return status; }; - /* Obj */ - obj = obj_init(); - if (!obj) { - printf("Error: Obj initialization failed (%d)\n", status); - return status; - } - /* Thread */ status = thread_init(); if (status) { @@ -174,10 +166,10 @@ main(int argc, char **argv) cli_script_process(app.script_name, app.conn.msg_in_len_max, app.conn.msg_out_len_max, - obj); + NULL); /* Connectivity */ - app.conn.msg_handle_arg = obj; + app.conn.msg_handle_arg = NULL; conn = conn_init(&app.conn); if (!conn) { printf("Error: Connectivity initialization failed (%d)\n", diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c index f1a50133f4..a5c09e7219 100644 --- a/examples/pipeline/obj.c +++ b/examples/pipeline/obj.c @@ -4,35 +4,14 @@ #include #include -#include -#ifdef RTE_EXEC_ENV_LINUX -#include -#include -#endif -#include -#include -#include #include #include -#include #include "obj.h" /* - * link - */ -TAILQ_HEAD(link_list, link); - -/* - * obj - */ -struct obj { - struct link_list link_list; -}; - -/* - * link + * ethdev */ static struct rte_eth_conf port_conf_default = { .link_speeds = 0, @@ -59,7 +38,7 @@ static struct rte_eth_conf port_conf_default = { static int rss_setup(uint16_t port_id, uint16_t reta_size, - struct link_params_rss *rss) + struct ethdev_params_rss *rss) { struct rte_eth_rss_reta_entry64 reta_conf[RETA_CONF_SIZE]; uint32_t i; @@ -88,69 +67,64 @@ rss_setup(uint16_t port_id, return status; } -struct link * -link_create(struct obj *obj, const char *name, struct link_params *params) +int +ethdev_config(const char *name, struct ethdev_params *params) { struct rte_eth_dev_info port_info; struct rte_eth_conf port_conf; - struct link *link; - struct link_params_rss *rss; + struct ethdev_params_rss *rss; struct rte_mempool *mempool; - uint32_t cpu_id, i; - int status; + uint32_t i; + int numa_node, status; uint16_t port_id = 0; /* Check input params */ - if ((name == NULL) || - link_find(obj, name) || - (params == NULL) || - (params->rx.n_queues == 0) || - (params->rx.queue_size == 0) || - (params->tx.n_queues == 0) || - (params->tx.queue_size == 0)) - return NULL; + if (!name || + !name[0] || + !params || + !params->rx.n_queues || + !params->rx.queue_size || + !params->tx.n_queues || + !params->tx.queue_size) + return -EINVAL; status = rte_eth_dev_get_port_by_name(name, &port_id); if (status) - return NULL; + return -EINVAL; - if (rte_eth_dev_info_get(port_id, &port_info) != 0) - return NULL; + status = rte_eth_dev_info_get(port_id, &port_info); + if (status) + return -EINVAL; mempool = rte_mempool_lookup(params->rx.mempool_name); if (!mempool) - return NULL; + return -EINVAL; rss = params->rx.rss; if (rss) { - if ((port_info.reta_size == 0) || - (port_info.reta_size > RTE_ETH_RSS_RETA_SIZE_512)) - return NULL; + if (!port_info.reta_size || port_info.reta_size > RTE_ETH_RSS_RETA_SIZE_512) + return -EINVAL; - if ((rss->n_queues == 0) || - (rss->n_queues >= LINK_RXQ_RSS_MAX)) - return NULL; + if (!rss->n_queues || rss->n_queues >= ETHDEV_RXQ_RSS_MAX) + return -EINVAL; for (i = 0; i < rss->n_queues; i++) if (rss->queue_id[i] >= port_info.max_rx_queues) - return NULL; + return -EINVAL; } - /** - * Resource create - */ /* Port */ memcpy(&port_conf, &port_conf_default, sizeof(port_conf)); if (rss) { + uint64_t rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP; + port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS; - port_conf.rx_adv_conf.rss_conf.rss_hf = - (RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP) & - port_info.flow_type_rss_offloads; + port_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf & port_info.flow_type_rss_offloads; } - cpu_id = (uint32_t) rte_eth_dev_socket_id(port_id); - if (cpu_id == (uint32_t) SOCKET_ID_ANY) - cpu_id = 0; + numa_node = rte_eth_dev_socket_id(port_id); + if (numa_node == SOCKET_ID_ANY) + numa_node = 0; status = rte_eth_dev_configure( port_id, @@ -159,12 +133,12 @@ link_create(struct obj *obj, const char *name, struct link_params *params) &port_conf); if (status < 0) - return NULL; + return -EINVAL; if (params->promiscuous) { status = rte_eth_promiscuous_enable(port_id); - if (status != 0) - return NULL; + if (status) + return -EINVAL; } /* Port RX */ @@ -173,12 +147,12 @@ link_create(struct obj *obj, const char *name, struct link_params *params) port_id, i, params->rx.queue_size, - cpu_id, + numa_node, NULL, mempool); if (status < 0) - return NULL; + return -EINVAL; } /* Port TX */ @@ -187,24 +161,24 @@ link_create(struct obj *obj, const char *name, struct link_params *params) port_id, i, params->tx.queue_size, - cpu_id, + numa_node, NULL); if (status < 0) - return NULL; + return -EINVAL; } /* Port start */ status = rte_eth_dev_start(port_id); if (status < 0) - return NULL; + return -EINVAL; if (rss) { status = rss_setup(port_id, port_info.reta_size, rss); if (status) { rte_eth_dev_stop(port_id); - return NULL; + return -EINVAL; } } @@ -212,84 +186,8 @@ link_create(struct obj *obj, const char *name, struct link_params *params) status = rte_eth_dev_set_link_up(port_id); if ((status < 0) && (status != -ENOTSUP)) { rte_eth_dev_stop(port_id); - return NULL; - } - - /* Node allocation */ - link = calloc(1, sizeof(struct link)); - if (link == NULL) { - rte_eth_dev_stop(port_id); - return NULL; + return -EINVAL; } - /* Node fill in */ - strlcpy(link->name, name, sizeof(link->name)); - link->port_id = port_id; - link->n_rxq = params->rx.n_queues; - link->n_txq = params->tx.n_queues; - - /* Node add to list */ - TAILQ_INSERT_TAIL(&obj->link_list, link, node); - - return link; -} - -int -link_is_up(struct obj *obj, const char *name) -{ - struct rte_eth_link link_params; - struct link *link; - - /* Check input params */ - if (!obj || !name) - return 0; - - link = link_find(obj, name); - if (link == NULL) - return 0; - - /* Resource */ - if (rte_eth_link_get(link->port_id, &link_params) < 0) - return 0; - - return (link_params.link_status == RTE_ETH_LINK_DOWN) ? 0 : 1; -} - -struct link * -link_find(struct obj *obj, const char *name) -{ - struct link *link; - - if (!obj || !name) - return NULL; - - TAILQ_FOREACH(link, &obj->link_list, node) - if (strcmp(link->name, name) == 0) - return link; - - return NULL; -} - -struct link * -link_next(struct obj *obj, struct link *link) -{ - return (link == NULL) ? - TAILQ_FIRST(&obj->link_list) : TAILQ_NEXT(link, node); -} - -/* - * obj - */ -struct obj * -obj_init(void) -{ - struct obj *obj; - - obj = calloc(1, sizeof(struct obj)); - if (!obj) - return NULL; - - TAILQ_INIT(&obj->link_list); - - return obj; + return 0; } diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h index dbbc6d39a0..fb091f4ba7 100644 --- a/examples/pipeline/obj.h +++ b/examples/pipeline/obj.h @@ -6,41 +6,25 @@ #define _INCLUDE_OBJ_H_ #include -#include - -#include -#include - -#ifndef NAME_SIZE -#define NAME_SIZE 64 -#endif - -/* - * obj - */ -struct obj; - -struct obj * -obj_init(void); /* - * link + * ethdev */ -#ifndef LINK_RXQ_RSS_MAX -#define LINK_RXQ_RSS_MAX 16 +#ifndef ETHDEV_RXQ_RSS_MAX +#define ETHDEV_RXQ_RSS_MAX 16 #endif -struct link_params_rss { - uint32_t queue_id[LINK_RXQ_RSS_MAX]; +struct ethdev_params_rss { + uint32_t queue_id[ETHDEV_RXQ_RSS_MAX]; uint32_t n_queues; }; -struct link_params { +struct ethdev_params { struct { uint32_t n_queues; uint32_t queue_size; const char *mempool_name; - struct link_params_rss *rss; + struct ethdev_params_rss *rss; } rx; struct { @@ -51,26 +35,7 @@ struct link_params { int promiscuous; }; -struct link { - TAILQ_ENTRY(link) node; - char name[NAME_SIZE]; - uint16_t port_id; - uint32_t n_rxq; - uint32_t n_txq; -}; - -struct link * -link_create(struct obj *obj, - const char *name, - struct link_params *params); - int -link_is_up(struct obj *obj, const char *name); - -struct link * -link_find(struct obj *obj, const char *name); - -struct link * -link_next(struct obj *obj, struct link *link); +ethdev_config(const char *name, struct ethdev_params *params); #endif /* _INCLUDE_OBJ_H_ */ From patchwork Wed Jan 11 20:56:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121847 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 08D35423AF; Wed, 11 Jan 2023 21:56:51 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8138542D50; Wed, 11 Jan 2023 21:56:20 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 0829F42D3B for ; Wed, 11 Jan 2023 21:56:16 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470577; x=1705006577; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=K5movnkORz07XyPt96JrrRHaKqwK/rtHC5SFTDYHSaI=; b=PaTryglxdAZgQ5ORaRhT4vzqhTZL1We76nWptNLaShV4Z9pWAX3D35qg ZUuch6RHWP+CgpqfTGEkWjBs8EGOzqI4w002ln5FQ/gNf2NKkyD39+WL4 ahjPwV/Y+NyV9hBDM53DVjEav8msNn850oPtSRQ7q7G2uMetzghfmM1AV 75GRoYm2gpsxCs/WHuiYs5zfb7IILu/Am5n0N+vzlSXO+Ta5Vmabyvwej Q2G/+gGeetbDfD23UnkfEP9TKmbHW8tzKptgYy4VkQSlx3cizPRhC7QSW +NiJjKJ+Th0zKl+4VtCTcDjjVPT9Qj5+UXYLv5QgJ0f81bBDiVQ8sajdR A==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229783" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229783" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:16 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518860" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518860" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:15 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 05/11] examples/pipeline: support crypto devices Date: Wed, 11 Jan 2023 20:56:02 +0000 Message-Id: <20230111205608.87953-6-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add support for crypto devices in the application. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/obj.c | 61 +++++++++++++++++++++++++++++++++++++++++ examples/pipeline/obj.h | 11 ++++++++ 2 files changed, 72 insertions(+) diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c index a5c09e7219..078395c6aa 100644 --- a/examples/pipeline/obj.c +++ b/examples/pipeline/obj.c @@ -7,6 +7,7 @@ #include #include +#include #include "obj.h" @@ -191,3 +192,63 @@ ethdev_config(const char *name, struct ethdev_params *params) return 0; } + +/* + * cryptodev + */ +int +cryptodev_config(const char *name, struct cryptodev_params *params) +{ + struct rte_cryptodev_info dev_info; + struct rte_cryptodev_config dev_conf; + struct rte_cryptodev_qp_conf queue_conf; + uint8_t dev_id; + uint32_t socket_id, i; + int status; + + /* Check input parameters. */ + if (!name || + !params->n_queue_pairs || + !params->queue_size) + return -EINVAL; + + /* Find the crypto device. */ + status = rte_cryptodev_get_dev_id(name); + if (status < 0) + return -EINVAL; + + dev_id = (uint8_t)status; + + rte_cryptodev_info_get(dev_id, &dev_info); + if (params->n_queue_pairs > dev_info.max_nb_queue_pairs) + return -EINVAL; + + socket_id = rte_cryptodev_socket_id(dev_id); + + /* Configure the crypto device. */ + dev_conf.socket_id = socket_id; + dev_conf.nb_queue_pairs = params->n_queue_pairs; + dev_conf.ff_disable = 0; + + status = rte_cryptodev_configure(dev_id, &dev_conf); + if (status) + return status; + + /* Configure the crypto device queue pairs. */ + queue_conf.nb_descriptors = params->queue_size; + queue_conf.mp_session = NULL; + queue_conf.mp_session_private = NULL; + + for (i = 0; i < params->n_queue_pairs; i++) { + status = rte_cryptodev_queue_pair_setup(dev_id, i, &queue_conf, socket_id); + if (status) + return status; + } + + /* Start the crypto device. */ + status = rte_cryptodev_start(dev_id); + if (status) + return status; + + return 0; +} diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h index fb091f4ba7..0f103be6a7 100644 --- a/examples/pipeline/obj.h +++ b/examples/pipeline/obj.h @@ -38,4 +38,15 @@ struct ethdev_params { int ethdev_config(const char *name, struct ethdev_params *params); +/* + * cryptodev + */ +struct cryptodev_params { + uint32_t n_queue_pairs; + uint32_t queue_size; +}; + +int +cryptodev_config(const char *name, struct cryptodev_params *params); + #endif /* _INCLUDE_OBJ_H_ */ From patchwork Wed Jan 11 20:56:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121848 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 16B05423AF; Wed, 11 Jan 2023 21:56:57 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5570042D4A; Wed, 11 Jan 2023 21:56:21 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 9EB5240A7D for ; Wed, 11 Jan 2023 21:56:17 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470577; x=1705006577; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+H3MltcnZ8fzvy/BpEhkr8JhVDasw344mTX0ievIsL8=; b=RrX5U1RqKDnEq7LA6nUCpjOmQUaXQS4qs8s1KBgcwQytw9dIZ3w4s66v IYlebxkHY0UNKILK6GF41OkVDtJ+cb9WrUxcz8i0np9AA2o4nbn5w7PXm WQDiVpR28ZhVFr9MDpc0lplH6c0VmDdFndf1Gm/U5dR4q/GWAIfwy9vgb sYdjLMr27M8XL/YUAVhlbKi54PNCcqKE+wMrQA4ZLwUEvZ0JIKsMxZtHl fBlRjQiV1+b35PL/UI2SpR/fKC+ARM1aNHpq+Z5HV3X+BJwIh9EYsY/L0 1qQ6yzW/sDICRqIztr7Km2mIewOM1+hPJ+5B/YIFHeKHeRuVFhQcCdYpw w==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229785" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229785" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:17 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518870" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518870" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:16 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 06/11] examples/pipeline: add CLI command for crypto device Date: Wed, 11 Jan 2023 20:56:03 +0000 Message-Id: <20230111205608.87953-7-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add CLI command for the configuration of crypto devices. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/cli.c | 63 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c index 37fc6f9551..47c1adf772 100644 --- a/examples/pipeline/cli.c +++ b/examples/pipeline/cli.c @@ -521,6 +521,58 @@ cmd_ring(char **tokens, } } +static const char cmd_cryptodev_help[] = +"cryptodev queues qsize \n"; + +static void +cmd_cryptodev(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj __rte_unused) +{ + struct cryptodev_params params; + char *cryptodev_name; + int status; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (strcmp(tokens[0], "cryptodev")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cryptodev"); + return; + } + + cryptodev_name = tokens[1]; + + if (strcmp(tokens[2], "queues")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "queues"); + return; + } + + if (parser_read_uint32(¶ms.n_queue_pairs, tokens[3])) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_queue_pairs"); + return; + } + + if (strcmp(tokens[4], "qsize")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); + return; + } + + + if (parser_read_uint32(¶ms.queue_size, tokens[5])) { + snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); + return; + } + + status = cryptodev_config(cryptodev_name, ¶ms); + if (status) + snprintf(out, out_size, "Crypto device configuration failed (%d).\n", status); +} + static const char cmd_pipeline_codegen_help[] = "pipeline codegen \n"; @@ -2990,6 +3042,7 @@ cmd_help(char **tokens, "\tethdev\n" "\tethdev show\n" "\tring\n" + "\tcryptodev\n" "\tpipeline codegen\n" "\tpipeline libbuild\n" "\tpipeline build\n" @@ -3041,6 +3094,11 @@ cmd_help(char **tokens, return; } + if (!strcmp(tokens[0], "cryptodev")) { + snprintf(out, out_size, "\n%s\n", cmd_cryptodev_help); + return; + } + if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) { snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help); @@ -3296,6 +3354,11 @@ cli_process(char *in, char *out, size_t out_size, void *obj) return; } + if (!strcmp(tokens[0], "cryptodev")) { + cmd_cryptodev(tokens, n_tokens, out, out_size, obj); + return; + } + if (strcmp(tokens[0], "pipeline") == 0) { if ((n_tokens >= 3) && (strcmp(tokens[1], "codegen") == 0)) { From patchwork Wed Jan 11 20:56:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121849 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 900CF423AF; Wed, 11 Jan 2023 21:57:02 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 460FF42D58; Wed, 11 Jan 2023 21:56:22 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id A476142D43 for ; Wed, 11 Jan 2023 21:56:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470578; x=1705006578; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=m8kqkXJ9ngkUmnF2mgSDGB4G10UZU0EJJwwCWsomtk0=; b=HcVV+z7xt2jhClUmKTaEzQxRBOTd5TSnar1h7Jg8ZnX630UQd7uBZW1t y8Rd8OrSbxM/cLYHhmP7Xfvk06rARbAw//MLhAwp1SUPEDJLfRuIteCUR eOrU6ibIM8OjtwZ3wz6qE9mTesbqNkpoa6In9tVlNHdLgeUnqUOp/0A5S 8FCNEBC9/KjfP8rCyYE/GxJMLZDbfROO4QozBCNWT6t+xwsBbvQccO/w+ lXe4kOrse86rhSGDG4WTDob43PQaHDnkvyFZVx9KspmElI8h8A+QUKjmq M/nB+xKQFATY5ctZFKdVOocJp7d2gzSjgo6CXlwTpRyKx/oaiQmG4QQk/ A==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229788" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229788" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:18 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518881" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518881" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:17 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 07/11] examples/pipeline: add IPsec CLI commands Date: Wed, 11 Jan 2023 20:56:04 +0000 Message-Id: <20230111205608.87953-8-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add CLI commands for IPsec block configuration. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/cli.c | 298 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c index 47c1adf772..efe2ff61db 100644 --- a/examples/pipeline/cli.c +++ b/examples/pipeline/cli.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "cli.h" @@ -2909,6 +2910,263 @@ cmd_pipeline_mirror_session(char **tokens, } } +static const char cmd_ipsec_create_help[] = +"ipsec create " +"in out " +"cryptodev cryptoq " +"bsz " +"samax " +"numa \n"; + +static void +cmd_ipsec_create(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj __rte_unused) +{ + struct rte_swx_ipsec_params p; + struct rte_swx_ipsec *ipsec; + char *ipsec_instance_name; + uint32_t numa_node; + int status; + + if (n_tokens != 20) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + ipsec_instance_name = tokens[1]; + + if (strcmp(tokens[2], "create")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "create"); + return; + } + + if (strcmp(tokens[3], "in")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + p.ring_in_name = tokens[4]; + + if (strcmp(tokens[5], "out")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); + return; + } + + p.ring_out_name = tokens[6]; + + if (strcmp(tokens[7], "cryptodev")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cryptodev"); + return; + } + + p.crypto_dev_name = tokens[8]; + + if (strcmp(tokens[9], "cryptoq")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cryptoq"); + return; + } + + if (parser_read_uint32(&p.crypto_dev_queue_pair_id, tokens[10])) { + snprintf(out, out_size, MSG_ARG_INVALID, "crypto_dev_queue_pair_id"); + return; + } + + if (strcmp(tokens[11], "bsz")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); + return; + } + + if (parser_read_uint32(&p.bsz.ring_rd, tokens[12])) { + snprintf(out, out_size, MSG_ARG_INVALID, "ring_rd_bsz"); + return; + } + + if (parser_read_uint32(&p.bsz.ring_wr, tokens[13])) { + snprintf(out, out_size, MSG_ARG_INVALID, "ring_wr_bsz"); + return; + } + + if (parser_read_uint32(&p.bsz.crypto_wr, tokens[14])) { + snprintf(out, out_size, MSG_ARG_INVALID, "crypto_wr_bsz"); + return; + } + + if (parser_read_uint32(&p.bsz.crypto_rd, tokens[15])) { + snprintf(out, out_size, MSG_ARG_INVALID, "crypto_rd_bsz"); + return; + } + + if (strcmp(tokens[16], "samax")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "samax"); + return; + } + + if (parser_read_uint32(&p.n_sa_max, tokens[17])) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_sa_max"); + return; + } + + if (strcmp(tokens[18], "numa")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa"); + return; + } + + if (parser_read_uint32(&numa_node, tokens[19])) { + snprintf(out, out_size, MSG_ARG_INVALID, "numa_node"); + return; + } + + status = rte_swx_ipsec_create(&ipsec, + ipsec_instance_name, + &p, + (int)numa_node); + if (status) + snprintf(out, out_size, "IPsec instance creation failed (%d).\n", status); +} + +static const char cmd_ipsec_sa_add_help[] = +"ipsec sa add \n"; + +static void +cmd_ipsec_sa_add(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj __rte_unused) +{ + struct rte_swx_ipsec *ipsec; + char *ipsec_instance_name, *file_name, *line = NULL; + FILE *file = NULL; + uint32_t line_id = 0; + + if (n_tokens != 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + ipsec_instance_name = tokens[1]; + ipsec = rte_swx_ipsec_find(ipsec_instance_name); + if (!ipsec) { + snprintf(out, out_size, MSG_ARG_INVALID, "ipsec_instance_name"); + goto free; + } + + if (strcmp(tokens[2], "sa")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "sa"); + goto free; + } + + if (strcmp(tokens[3], "add")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); + goto free; + } + + file_name = tokens[4]; + file = fopen(file_name, "r"); + if (!file) { + snprintf(out, out_size, "Cannot open file %s.\n", file_name); + goto free; + } + + /* Buffer allocation. */ + line = malloc(MAX_LINE_SIZE); + if (!line) { + snprintf(out, out_size, MSG_OUT_OF_MEMORY); + goto free; + } + + /* File read. */ + for (line_id = 1; ; line_id++) { + struct rte_swx_ipsec_sa_params *sa; + const char *err_msg; + uint32_t sa_id = 0; + int is_blank_or_comment, status = 0; + + if (fgets(line, MAX_LINE_SIZE, file) == NULL) + break; + + /* Read SA from file. */ + sa = rte_swx_ipsec_sa_read(ipsec, line, &is_blank_or_comment, &err_msg); + if (!sa) { + if (is_blank_or_comment) + continue; + + snprintf(out, out_size, "Invalid SA in file \"%s\" at line %u: \"%s\"\n", + file_name, line_id, err_msg); + goto free; + } + + snprintf(out, out_size, "%s", line); + out_size -= strlen(out); + out += strlen(out); + + /* Add the SA to the IPsec instance. Free the SA. */ + status = rte_swx_ipsec_sa_add(ipsec, sa, &sa_id); + if (status) + snprintf(out, out_size, "\t: Error (%d)\n", status); + else + snprintf(out, out_size, "\t: OK (SA ID = %u)\n", sa_id); + out_size -= strlen(out); + out += strlen(out); + + free(sa); + if (status) + goto free; + } + +free: + if (file) + fclose(file); + free(line); +} + +static const char cmd_ipsec_sa_delete_help[] = +"ipsec sa delete \n"; + +static void +cmd_ipsec_sa_delete(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj __rte_unused) +{ + struct rte_swx_ipsec *ipsec; + char *ipsec_instance_name; + uint32_t sa_id; + + if (n_tokens != 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + ipsec_instance_name = tokens[1]; + ipsec = rte_swx_ipsec_find(ipsec_instance_name); + if (!ipsec) { + snprintf(out, out_size, MSG_ARG_INVALID, "ipsec_instance_name"); + return; + } + + if (strcmp(tokens[2], "sa")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "sa"); + return; + } + + if (strcmp(tokens[3], "delete")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); + return; + } + + if (parser_read_uint32(&sa_id, tokens[4])) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa_id"); + return; + } + + rte_swx_ipsec_sa_delete(ipsec, sa_id); +} + static const char cmd_thread_pipeline_enable_help[] = "thread pipeline enable [ period ]\n"; @@ -3067,6 +3325,9 @@ cmd_help(char **tokens, "\tpipeline meter stats\n" "\tpipeline stats\n" "\tpipeline mirror session\n" + "\tipsec create\n" + "\tipsec sa add\n" + "\tipsec sa delete\n" "\tthread pipeline enable\n" "\tthread pipeline disable\n\n"); return; @@ -3291,6 +3552,26 @@ cmd_help(char **tokens, return; } + if (!strcmp(tokens[0], "ipsec") && + (n_tokens == 2) && !strcmp(tokens[1], "create")) { + snprintf(out, out_size, "\n%s\n", cmd_ipsec_create_help); + return; + } + + if (!strcmp(tokens[0], "ipsec") && + (n_tokens == 3) && !strcmp(tokens[1], "sa") + && !strcmp(tokens[2], "add")) { + snprintf(out, out_size, "\n%s\n", cmd_ipsec_sa_add_help); + return; + } + + if (!strcmp(tokens[0], "ipsec") && + (n_tokens == 3) && !strcmp(tokens[1], "sa") + && !strcmp(tokens[2], "delete")) { + snprintf(out, out_size, "\n%s\n", cmd_ipsec_sa_delete_help); + return; + } + if ((n_tokens == 3) && (strcmp(tokens[0], "thread") == 0) && (strcmp(tokens[1], "pipeline") == 0)) { @@ -3539,6 +3820,23 @@ cli_process(char *in, char *out, size_t out_size, void *obj) } } + if (!strcmp(tokens[0], "ipsec")) { + if (n_tokens >= 3 && !strcmp(tokens[2], "create")) { + cmd_ipsec_create(tokens, n_tokens, out, out_size, obj); + return; + } + + if (n_tokens >= 4 && !strcmp(tokens[2], "sa") && !strcmp(tokens[3], "add")) { + cmd_ipsec_sa_add(tokens, n_tokens, out, out_size, obj); + return; + } + + if (n_tokens >= 4 && !strcmp(tokens[2], "sa") && !strcmp(tokens[3], "delete")) { + cmd_ipsec_sa_delete(tokens, n_tokens, out, out_size, obj); + return; + } + } + if (strcmp(tokens[0], "thread") == 0) { if ((n_tokens >= 5) && (strcmp(tokens[4], "enable") == 0)) { From patchwork Wed Jan 11 20:56:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121850 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0EE96423AF; Wed, 11 Jan 2023 21:57:08 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2C35542D5C; Wed, 11 Jan 2023 21:56:23 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 3678742D4A for ; Wed, 11 Jan 2023 21:56:20 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470580; x=1705006580; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kgBaGHCUDLvPAEBajTO+JNgjDAeYHZZczwVIoAUlZGA=; b=Vl9f4ZqHsHV2cQ2UjICoEzaXtG1FI1oMnQxiuHfZUKji+0xKwcGKDvXX /sq4AgYhRWM9JtTrHE6EQbXs17fcHyu9kXAhv0Ki+TA3a5hRt99qs2/c6 hOYhlN18byDrOZ2X35nu8d8Lf6vVN4Ms1VeYjfxaaU1VlWSsIbLhZt8Bt Sgy7kQ4tPZarHc5T3k0o65Z/lPoxaHSCjVbdSWDTkaRX9U3kDkq2/ZlY/ Rd/sqPYldrWhRAn5rjkLolriDvKl4QPWAXgpmaIZotsvLCfOgYhQRMuHO UvNtlIEXqdxNqN5YZc4TnpwvDpjVR0kctzv+RSVj4QofJSoxvqQ9Lb8pl A==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229791" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229791" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:19 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518892" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518892" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:18 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 08/11] examples/pipeline: rework the thread configuration updates Date: Wed, 11 Jan 2023 20:56:05 +0000 Message-Id: <20230111205608.87953-9-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Previously, the configuration updates for the data plane threads were performed through message queues. Now, this mechanism is replaced by the control thread updating the mirror copy of the data plane thread configuration followed by pointer swapping. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/cli.c | 154 ++--- examples/pipeline/examples/fib.cli | 2 +- examples/pipeline/examples/hash_func.cli | 2 +- examples/pipeline/examples/l2fwd.cli | 2 +- examples/pipeline/examples/l2fwd_macswp.cli | 2 +- .../pipeline/examples/l2fwd_macswp_pcap.cli | 2 +- examples/pipeline/examples/l2fwd_pcap.cli | 2 +- examples/pipeline/examples/learner.cli | 2 +- examples/pipeline/examples/meter.cli | 2 +- examples/pipeline/examples/mirroring.cli | 2 +- examples/pipeline/examples/recirculation.cli | 2 +- examples/pipeline/examples/registers.cli | 2 +- examples/pipeline/examples/selector.cli | 2 +- examples/pipeline/examples/varbit.cli | 2 +- examples/pipeline/examples/vxlan.cli | 2 +- examples/pipeline/examples/vxlan_pcap.cli | 2 +- examples/pipeline/thread.c | 586 ++++-------------- examples/pipeline/thread.h | 17 +- 18 files changed, 217 insertions(+), 570 deletions(-) diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c index efe2ff61db..d48cbb6240 100644 --- a/examples/pipeline/cli.c +++ b/examples/pipeline/cli.c @@ -3167,119 +3167,86 @@ cmd_ipsec_sa_delete(char **tokens, rte_swx_ipsec_sa_delete(ipsec, sa_id); } -static const char cmd_thread_pipeline_enable_help[] = -"thread pipeline enable [ period ]\n"; - -#ifndef TIMER_PERIOD_MS_DEFAULT -#define TIMER_PERIOD_MS_DEFAULT 10 -#endif +static const char cmd_pipeline_enable_help[] = +"pipeline enable thread \n"; static void -cmd_thread_pipeline_enable(char **tokens, - uint32_t n_tokens, - char *out, - size_t out_size, - void *obj __rte_unused) +cmd_pipeline_enable(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj __rte_unused) { char *pipeline_name; struct rte_swx_pipeline *p; - uint32_t thread_id, timer_period_ms = TIMER_PERIOD_MS_DEFAULT; + uint32_t thread_id; int status; - if ((n_tokens != 5) && (n_tokens != 7)) { + if (n_tokens != 5) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } - if (parser_read_uint32(&thread_id, tokens[1]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); - return; - } - - if (strcmp(tokens[2], "pipeline") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); - return; - } - - pipeline_name = tokens[3]; + pipeline_name = tokens[1]; p = rte_swx_pipeline_find(pipeline_name); if (!p) { snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); return; } - if (strcmp(tokens[4], "enable") != 0) { + if (strcmp(tokens[2], "enable") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); return; } - if (n_tokens == 7) { - if (strcmp(tokens[5], "period") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period"); - return; - } + if (strcmp(tokens[3], "thread") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread"); + return; + } - if (parser_read_uint32(&timer_period_ms, tokens[6]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms"); - return; - } + if (parser_read_uint32(&thread_id, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); + return; } - status = thread_pipeline_enable(thread_id, p, timer_period_ms); + status = pipeline_enable(p, thread_id); if (status) { - snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); + snprintf(out, out_size, MSG_CMD_FAIL, "pipeline enable"); return; } } -static const char cmd_thread_pipeline_disable_help[] = -"thread pipeline disable\n"; +static const char cmd_pipeline_disable_help[] = +"pipeline disable\n"; static void -cmd_thread_pipeline_disable(char **tokens, - uint32_t n_tokens, - char *out, - size_t out_size, - void *obj __rte_unused) +cmd_pipeline_disable(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj __rte_unused) { struct rte_swx_pipeline *p; char *pipeline_name; - uint32_t thread_id; - int status; - if (n_tokens != 5) { + if (n_tokens != 3) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } - if (parser_read_uint32(&thread_id, tokens[1]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); - return; - } - - if (strcmp(tokens[2], "pipeline") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); - return; - } - - pipeline_name = tokens[3]; + pipeline_name = tokens[1]; p = rte_swx_pipeline_find(pipeline_name); if (!p) { snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); return; } - if (strcmp(tokens[4], "disable") != 0) { + if (strcmp(tokens[2], "disable") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); return; } - status = thread_pipeline_disable(thread_id, p); - if (status) { - snprintf(out, out_size, MSG_CMD_FAIL, - "thread pipeline disable"); - return; - } + pipeline_disable(p); } static void @@ -3325,11 +3292,12 @@ cmd_help(char **tokens, "\tpipeline meter stats\n" "\tpipeline stats\n" "\tpipeline mirror session\n" + "\tpipeline enable\n" + "\tpipeline disable\n\n" "\tipsec create\n" "\tipsec sa add\n" "\tipsec sa delete\n" - "\tthread pipeline enable\n" - "\tthread pipeline disable\n\n"); + ); return; } @@ -3552,6 +3520,18 @@ cmd_help(char **tokens, return; } + if (!strcmp(tokens[0], "pipeline") && + (n_tokens == 2) && !strcmp(tokens[1], "enable")) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_enable_help); + return; + } + + if (!strcmp(tokens[0], "pipeline") && + (n_tokens == 2) && !strcmp(tokens[1], "disable")) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_disable_help); + return; + } + if (!strcmp(tokens[0], "ipsec") && (n_tokens == 2) && !strcmp(tokens[1], "create")) { snprintf(out, out_size, "\n%s\n", cmd_ipsec_create_help); @@ -3572,22 +3552,6 @@ cmd_help(char **tokens, return; } - if ((n_tokens == 3) && - (strcmp(tokens[0], "thread") == 0) && - (strcmp(tokens[1], "pipeline") == 0)) { - if (strcmp(tokens[2], "enable") == 0) { - snprintf(out, out_size, "\n%s\n", - cmd_thread_pipeline_enable_help); - return; - } - - if (strcmp(tokens[2], "disable") == 0) { - snprintf(out, out_size, "\n%s\n", - cmd_thread_pipeline_disable_help); - return; - } - } - snprintf(out, out_size, "Invalid command\n"); } @@ -3818,6 +3782,16 @@ cli_process(char *in, char *out, size_t out_size, void *obj) cmd_pipeline_mirror_session(tokens, n_tokens, out, out_size, obj); return; } + + if (n_tokens >= 3 && !strcmp(tokens[2], "enable")) { + cmd_pipeline_enable(tokens, n_tokens, out, out_size, obj); + return; + } + + if (n_tokens >= 3 && !strcmp(tokens[2], "disable")) { + cmd_pipeline_disable(tokens, n_tokens, out, out_size, obj); + return; + } } if (!strcmp(tokens[0], "ipsec")) { @@ -3837,22 +3811,6 @@ cli_process(char *in, char *out, size_t out_size, void *obj) } } - if (strcmp(tokens[0], "thread") == 0) { - if ((n_tokens >= 5) && - (strcmp(tokens[4], "enable") == 0)) { - cmd_thread_pipeline_enable(tokens, n_tokens, - out, out_size, obj); - return; - } - - if ((n_tokens >= 5) && - (strcmp(tokens[4], "disable") == 0)) { - cmd_thread_pipeline_disable(tokens, n_tokens, - out, out_size, obj); - return; - } - } - snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); } diff --git a/examples/pipeline/examples/fib.cli b/examples/pipeline/examples/fib.cli index 2450dc9ca4..d2485cefe0 100644 --- a/examples/pipeline/examples/fib.cli +++ b/examples/pipeline/examples/fib.cli @@ -54,4 +54,4 @@ pipeline PIPELINE0 commit ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/hash_func.cli b/examples/pipeline/examples/hash_func.cli index 3840e47a2b..2c20f7a7a0 100644 --- a/examples/pipeline/examples/hash_func.cli +++ b/examples/pipeline/examples/hash_func.cli @@ -32,4 +32,4 @@ pipeline PIPELINE0 build lib /tmp/hash_func.so io ./examples/pipeline/examples/e ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/l2fwd.cli b/examples/pipeline/examples/l2fwd.cli index c5505df296..383fe346c0 100644 --- a/examples/pipeline/examples/l2fwd.cli +++ b/examples/pipeline/examples/l2fwd.cli @@ -32,4 +32,4 @@ pipeline PIPELINE0 build lib /tmp/l2fwd.so io ./examples/pipeline/examples/ethde ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/l2fwd_macswp.cli b/examples/pipeline/examples/l2fwd_macswp.cli index bd700707f5..d02cb2c470 100644 --- a/examples/pipeline/examples/l2fwd_macswp.cli +++ b/examples/pipeline/examples/l2fwd_macswp.cli @@ -32,4 +32,4 @@ pipeline PIPELINE0 build lib /tmp/l2fwd_macswp.so io ./examples/pipeline/example ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/l2fwd_macswp_pcap.cli b/examples/pipeline/examples/l2fwd_macswp_pcap.cli index aa64b32ab2..d4ea449e03 100644 --- a/examples/pipeline/examples/l2fwd_macswp_pcap.cli +++ b/examples/pipeline/examples/l2fwd_macswp_pcap.cli @@ -28,4 +28,4 @@ pipeline PIPELINE0 build lib /tmp/l2fwd_macswp.so io ./examples/pipeline/example ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/l2fwd_pcap.cli b/examples/pipeline/examples/l2fwd_pcap.cli index 619d17474f..8a25c98096 100644 --- a/examples/pipeline/examples/l2fwd_pcap.cli +++ b/examples/pipeline/examples/l2fwd_pcap.cli @@ -28,4 +28,4 @@ pipeline PIPELINE0 build lib /tmp/l2fwd.so io ./examples/pipeline/examples/pcap. ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/learner.cli b/examples/pipeline/examples/learner.cli index 42184be1c8..04c7b4d26f 100644 --- a/examples/pipeline/examples/learner.cli +++ b/examples/pipeline/examples/learner.cli @@ -32,4 +32,4 @@ pipeline PIPELINE0 build lib /tmp/learner.so io ./examples/pipeline/examples/eth ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/meter.cli b/examples/pipeline/examples/meter.cli index 0fa38b16b8..9e064dbb52 100644 --- a/examples/pipeline/examples/meter.cli +++ b/examples/pipeline/examples/meter.cli @@ -40,4 +40,4 @@ pipeline PIPELINE0 meter meters set profile platinum index from 0 to 15 ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/mirroring.cli b/examples/pipeline/examples/mirroring.cli index e7391de74b..da6bd338fb 100644 --- a/examples/pipeline/examples/mirroring.cli +++ b/examples/pipeline/examples/mirroring.cli @@ -42,4 +42,4 @@ pipeline PIPELINE0 mirror session 3 port 0 clone slow truncate 128 ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/recirculation.cli b/examples/pipeline/examples/recirculation.cli index 965c870fd4..f925179bf7 100644 --- a/examples/pipeline/examples/recirculation.cli +++ b/examples/pipeline/examples/recirculation.cli @@ -32,4 +32,4 @@ pipeline PIPELINE0 build lib /tmp/recirculation.so io ./examples/pipeline/exampl ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/registers.cli b/examples/pipeline/examples/registers.cli index aa775f71e5..58dde5fdf1 100644 --- a/examples/pipeline/examples/registers.cli +++ b/examples/pipeline/examples/registers.cli @@ -32,4 +32,4 @@ pipeline PIPELINE0 build lib /tmp/registers.so io ./examples/pipeline/examples/e ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/selector.cli b/examples/pipeline/examples/selector.cli index f0608de184..9af56cd0f1 100644 --- a/examples/pipeline/examples/selector.cli +++ b/examples/pipeline/examples/selector.cli @@ -42,4 +42,4 @@ pipeline PIPELINE0 selector s show ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/varbit.cli b/examples/pipeline/examples/varbit.cli index 648b8882c3..621e7f5627 100644 --- a/examples/pipeline/examples/varbit.cli +++ b/examples/pipeline/examples/varbit.cli @@ -32,4 +32,4 @@ pipeline PIPELINE0 build lib /tmp/varbit.so io ./examples/pipeline/examples/ethd ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/vxlan.cli b/examples/pipeline/examples/vxlan.cli index 4565adfaea..73eb29a6b2 100644 --- a/examples/pipeline/examples/vxlan.cli +++ b/examples/pipeline/examples/vxlan.cli @@ -40,4 +40,4 @@ pipeline PIPELINE0 commit ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/examples/vxlan_pcap.cli b/examples/pipeline/examples/vxlan_pcap.cli index 510c2ad870..828342408b 100644 --- a/examples/pipeline/examples/vxlan_pcap.cli +++ b/examples/pipeline/examples/vxlan_pcap.cli @@ -36,4 +36,4 @@ pipeline PIPELINE0 commit ; ; Pipelines-to-threads mapping. ; -thread 1 pipeline PIPELINE0 enable +pipeline PIPELINE0 enable thread 1 diff --git a/examples/pipeline/thread.c b/examples/pipeline/thread.c index 6d15f51fb2..3001bc0858 100644 --- a/examples/pipeline/thread.c +++ b/examples/pipeline/thread.c @@ -3,17 +3,11 @@ */ #include +#include +#include #include -#include #include -#include - -#include -#include -#include -#include -#include #include "obj.h" #include "thread.h" @@ -22,14 +16,6 @@ #define THREAD_PIPELINES_MAX 256 #endif -#ifndef THREAD_MSGQ_SIZE -#define THREAD_MSGQ_SIZE 64 -#endif - -#ifndef THREAD_TIMER_PERIOD_MS -#define THREAD_TIMER_PERIOD_MS 100 -#endif - /* Pipeline instruction quanta: Needs to be big enough to do some meaningful * work, but not too big to avoid starving any other pipelines mapped to the * same thread. For a pipeline that executes 10 instructions per packet, a @@ -40,509 +26,209 @@ #endif /** - * Control thread: data plane thread context + * In this design, there is a single control plane (CP) thread and one or multiple data plane (DP) + * threads. Each DP thread can run up to THREAD_PIPELINES_MAX pipelines and up to THREAD_BLOCKS_MAX + * blocks. + * + * The pipelines and blocks are single threaded, meaning that a given pipeline/block can be run by a + * single thread at any given time, so the same pipeline/block cannot show up in the list of + * pipelines/blocks of more than one thread at any specific moment. + * + * Each DP thread has its own context (struct thread instance), which it shares with the CP thread: + * - Read-write by the CP thread; + * - Read-only by the DP thread. */ struct thread { - struct rte_ring *msgq_req; - struct rte_ring *msgq_rsp; - - uint32_t enabled; -}; - -static struct thread thread[RTE_MAX_LCORE]; - -/** - * Data plane threads: context - */ -struct pipeline_data { - struct rte_swx_pipeline *p; - uint64_t timer_period; /* Measured in CPU cycles. */ - uint64_t time_next; -}; - -struct thread_data { - struct rte_swx_pipeline *p[THREAD_PIPELINES_MAX]; - uint32_t n_pipelines; - - struct pipeline_data pipeline_data[THREAD_PIPELINES_MAX]; - struct rte_ring *msgq_req; - struct rte_ring *msgq_rsp; - uint64_t timer_period; /* Measured in CPU cycles. */ - uint64_t time_next; - uint64_t time_next_min; + struct rte_swx_pipeline *pipelines[THREAD_PIPELINES_MAX]; + volatile uint64_t n_pipelines; + int enabled; } __rte_cache_aligned; -static struct thread_data thread_data[RTE_MAX_LCORE]; +static struct thread threads[RTE_MAX_LCORE]; /** - * Control thread: data plane thread init + * Control plane (CP) thread. */ -static void -thread_free(void) -{ - uint32_t i; - - for (i = 0; i < RTE_MAX_LCORE; i++) { - struct thread *t = &thread[i]; - - if (!rte_lcore_is_enabled(i)) - continue; - - /* MSGQs */ - rte_ring_free(t->msgq_req); - - rte_ring_free(t->msgq_rsp); - } -} - int thread_init(void) { - uint32_t i; - - RTE_LCORE_FOREACH_WORKER(i) { - char name[NAME_MAX]; - struct rte_ring *msgq_req, *msgq_rsp; - struct thread *t = &thread[i]; - struct thread_data *t_data = &thread_data[i]; - uint32_t cpu_id = rte_lcore_to_socket_id(i); - - /* MSGQs */ - snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-REQ", i); - - msgq_req = rte_ring_create(name, - THREAD_MSGQ_SIZE, - cpu_id, - RING_F_SP_ENQ | RING_F_SC_DEQ); - - if (msgq_req == NULL) { - thread_free(); - return -1; - } + uint32_t thread_id; - snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-RSP", i); + RTE_LCORE_FOREACH_WORKER(thread_id) { + struct thread *t = &threads[thread_id]; - msgq_rsp = rte_ring_create(name, - THREAD_MSGQ_SIZE, - cpu_id, - RING_F_SP_ENQ | RING_F_SC_DEQ); - - if (msgq_rsp == NULL) { - thread_free(); - return -1; - } - - /* Control thread records */ - t->msgq_req = msgq_req; - t->msgq_rsp = msgq_rsp; t->enabled = 1; - - /* Data plane thread records */ - t_data->n_pipelines = 0; - t_data->msgq_req = msgq_req; - t_data->msgq_rsp = msgq_rsp; - t_data->timer_period = - (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000; - t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period; - t_data->time_next_min = t_data->time_next; } return 0; } -static inline int -thread_is_running(uint32_t thread_id) +static uint32_t +pipeline_find(struct rte_swx_pipeline *p) { - enum rte_lcore_state_t thread_state; + uint32_t thread_id; - thread_state = rte_eal_get_lcore_state(thread_id); - return (thread_state == RUNNING) ? 1 : 0; -} - -/** - * Control thread & data plane threads: message passing - */ -enum thread_req_type { - THREAD_REQ_PIPELINE_ENABLE = 0, - THREAD_REQ_PIPELINE_DISABLE, - THREAD_REQ_MAX -}; - -struct thread_msg_req { - enum thread_req_type type; - - union { - struct { - struct rte_swx_pipeline *p; - uint32_t timer_period_ms; - } pipeline_enable; - - struct { - struct rte_swx_pipeline *p; - } pipeline_disable; - }; -}; - -struct thread_msg_rsp { - int status; -}; - -/** - * Control thread - */ -static struct thread_msg_req * -thread_msg_alloc(void) -{ - size_t size = RTE_MAX(sizeof(struct thread_msg_req), - sizeof(struct thread_msg_rsp)); - - return calloc(1, size); -} - -static void -thread_msg_free(struct thread_msg_rsp *rsp) -{ - free(rsp); -} - -static struct thread_msg_rsp * -thread_msg_send_recv(uint32_t thread_id, - struct thread_msg_req *req) -{ - struct thread *t = &thread[thread_id]; - struct rte_ring *msgq_req = t->msgq_req; - struct rte_ring *msgq_rsp = t->msgq_rsp; - struct thread_msg_rsp *rsp; - int status; - - /* send */ - do { - status = rte_ring_sp_enqueue(msgq_req, req); - } while (status == -ENOBUFS); - - /* recv */ - do { - status = rte_ring_sc_dequeue(msgq_rsp, (void **) &rsp); - } while (status != 0); - - return rsp; -} - -static int -thread_is_pipeline_enabled(uint32_t thread_id, struct rte_swx_pipeline *p) -{ - struct thread *t = &thread[thread_id]; - struct thread_data *td = &thread_data[thread_id]; - uint32_t i; - - if (!t->enabled) - return 0; /* Pipeline NOT enabled on this thread. */ - - for (i = 0; i < td->n_pipelines; i++) - if (td->p[i] == p) - return 1; /* Pipeline enabled on this thread. */ - - return 0 /* Pipeline NOT enabled on this thread. */; -} - -int -thread_pipeline_enable(uint32_t thread_id, struct rte_swx_pipeline *p, uint32_t timer_period_ms) -{ - struct thread *t; - struct thread_msg_req *req; - struct thread_msg_rsp *rsp; - int status; - - /* Check input params */ - if ((thread_id >= RTE_MAX_LCORE) || !p || !timer_period_ms) - return -1; - - t = &thread[thread_id]; - if (t->enabled == 0) - return -1; - - if (!thread_is_running(thread_id)) { - struct thread_data *td = &thread_data[thread_id]; - struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines]; - - if (td->n_pipelines >= THREAD_PIPELINES_MAX) - return -1; - - /* Data plane thread */ - td->p[td->n_pipelines] = p; - - tdp->p = p; - tdp->timer_period = (rte_get_tsc_hz() * timer_period_ms) / 1000; - tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period; + for (thread_id = 0; thread_id < RTE_MAX_LCORE; thread_id++) { + struct thread *t = &threads[thread_id]; + uint32_t i; - td->n_pipelines++; + if (!t->enabled) + continue; - return 0; + for (i = 0; i < t->n_pipelines; i++) + if (t->pipelines[i] == p) + break; } - /* Allocate request */ - req = thread_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = THREAD_REQ_PIPELINE_ENABLE; - req->pipeline_enable.p = p; - req->pipeline_enable.timer_period_ms = timer_period_ms; - - /* Send request and wait for response */ - rsp = thread_msg_send_recv(thread_id, req); - - /* Read response */ - status = rsp->status; - - /* Free response */ - thread_msg_free(rsp); - - /* Request completion */ - if (status) - return status; - - return 0; + return thread_id; } +/** + * Enable a given pipeline to run on a specific DP thread. + * + * CP thread: + * - Adds a new pipeline to the end of the DP thread pipeline list (t->pipelines[]); + * - Increments the DP thread number of pipelines (t->n_pipelines). It is important to make sure + * that t->pipelines[] update is completed BEFORE the t->n_pipelines update, hence the memory + * write barrier used below. + * + * DP thread: + * - Reads t->n_pipelines before starting every new iteration through t->pipelines[]. It detects + * the new pipeline when it sees the updated t->n_pipelines value; + * - If somehow the above condition is not met, so t->n_pipelines update is incorrectly taking + * place before the t->pipelines[] update is completed, then the DP thread will use an incorrect + * handle for the new pipeline, which can result in memory corruption or segmentation fault. + */ int -thread_pipeline_disable(uint32_t thread_id, struct rte_swx_pipeline *p) +pipeline_enable(struct rte_swx_pipeline *p, uint32_t thread_id) { struct thread *t; - struct thread_msg_req *req; - struct thread_msg_rsp *rsp; - int status; + uint64_t n_pipelines; /* Check input params */ - if ((thread_id >= RTE_MAX_LCORE) || !p) - return -1; - - t = &thread[thread_id]; - if (t->enabled == 0) - return -1; - - if (!thread_is_pipeline_enabled(thread_id, p)) - return 0; + if (!p || thread_id >= RTE_MAX_LCORE) + return -EINVAL; - if (!thread_is_running(thread_id)) { - struct thread_data *td = &thread_data[thread_id]; - uint32_t i; - - for (i = 0; i < td->n_pipelines; i++) { - struct pipeline_data *tdp = &td->pipeline_data[i]; - - if (tdp->p != p) - continue; - - /* Data plane thread */ - if (i < td->n_pipelines - 1) { - struct rte_swx_pipeline *pipeline_last = - td->p[td->n_pipelines - 1]; - struct pipeline_data *tdp_last = - &td->pipeline_data[td->n_pipelines - 1]; - - td->p[i] = pipeline_last; - memcpy(tdp, tdp_last, sizeof(*tdp)); - } - - td->n_pipelines--; - - break; - } + if (pipeline_find(p) < RTE_MAX_LCORE) + return -EEXIST; - return 0; - } - - /* Allocate request */ - req = thread_msg_alloc(); - if (req == NULL) - return -1; - - /* Write request */ - req->type = THREAD_REQ_PIPELINE_DISABLE; - req->pipeline_disable.p = p; - - /* Send request and wait for response */ - rsp = thread_msg_send_recv(thread_id, req); + t = &threads[thread_id]; + if (!t->enabled) + return -EINVAL; - /* Read response */ - status = rsp->status; + n_pipelines = t->n_pipelines; - /* Free response */ - thread_msg_free(rsp); + /* Check there is room for at least one more pipeline. */ + if (n_pipelines >= THREAD_PIPELINES_MAX) + return -ENOSPC; - /* Request completion */ - if (status) - return status; + /* Install the new pipeline. */ + t->pipelines[n_pipelines] = p; + rte_wmb(); + t->n_pipelines = n_pipelines + 1; return 0; } /** - * Data plane threads: message handling + * Disable a given pipeline from running on any DP thread. + * + * CP thread: + * - Detects the thread that is running the given pipeline, if any; + * - Writes the last pipeline handle (pipeline_last = t->pipelines[t->n_pipelines - 1]) on the + * position of the pipeline to be disabled (t->pipelines[i] = pipeline_last) and decrements the + * number of pipelines running on the current thread (t->n_pipelines--). This approach makes sure + * that no holes with invalid locations are ever developed within the t->pipelines[] array. + * - If the memory barrier below is present, then t->n_pipelines update is guaranteed to take place + * after the t->pipelines[] update is completed. The possible DP thread behaviors are detailed + * below, which are all valid: + * - Not run the removed pipeline at all, run all the other pipelines (including pipeline_last) + * exactly one time during the current dispatch loop iteration. This takes place when the DP + * thread sees the final value of t->n_pipelines; + * - Not run the removed pipeline at all, run all the other pipelines, except pipeline_last, + * exactly one time and the pipeline_last exactly two times during the current dispatch loop + * iteration. This takes place when the DP thread sees the initial value of t->n_pipelines. + * - If the memory barrier below is not present, then the t->n_pipelines update may be reordered by + * the CPU, so that it takes place before the t->pipelines[] update. The possible DP thread + * behaviors are detailed below, which are all valid: + * - Not run the removed pipeline at all, run all the other pipelines (including pipeline_last) + * exactly one time during the current dispatch loop iteration. This takes place when the DP + * thread sees the final values of the t->pipeline[] array; + * - Run the removed pipeline one last time, run all the other pipelines exactly one time, with + * the exception of the pipeline_last, which is not run during the current dispatch loop + * iteration. This takes place when the DP thread sees the initial values of t->pipeline[]. + * + * DP thread: + * - Reads t->n_pipelines before starting every new iteration through t->pipelines[]. */ -static inline struct thread_msg_req * -thread_msg_recv(struct rte_ring *msgq_req) -{ - struct thread_msg_req *req; - - int status = rte_ring_sc_dequeue(msgq_req, (void **) &req); - - if (status != 0) - return NULL; - - return req; -} - -static inline void -thread_msg_send(struct rte_ring *msgq_rsp, - struct thread_msg_rsp *rsp) -{ - int status; - - do { - status = rte_ring_sp_enqueue(msgq_rsp, rsp); - } while (status == -ENOBUFS); -} - -static struct thread_msg_rsp * -thread_msg_handle_pipeline_enable(struct thread_data *t, - struct thread_msg_req *req) +void +pipeline_disable(struct rte_swx_pipeline *p) { - struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req; - struct pipeline_data *p = &t->pipeline_data[t->n_pipelines]; - - /* Request */ - if (t->n_pipelines >= THREAD_PIPELINES_MAX) { - rsp->status = -1; - return rsp; - } - - t->p[t->n_pipelines] = req->pipeline_enable.p; - - p->p = req->pipeline_enable.p; - p->timer_period = (rte_get_tsc_hz() * - req->pipeline_enable.timer_period_ms) / 1000; - p->time_next = rte_get_tsc_cycles() + p->timer_period; + struct thread *t; + uint64_t n_pipelines; + uint32_t thread_id, i; - t->n_pipelines++; + /* Check input params */ + if (!p) + return; - /* Response */ - rsp->status = 0; - return rsp; -} + /* Find the thread that runs this pipeline. */ + thread_id = pipeline_find(p); + if (thread_id == RTE_MAX_LCORE) + return; -static struct thread_msg_rsp * -thread_msg_handle_pipeline_disable(struct thread_data *t, - struct thread_msg_req *req) -{ - struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req; - uint32_t n_pipelines = t->n_pipelines; - struct rte_swx_pipeline *pipeline = req->pipeline_disable.p; - uint32_t i; + t = &threads[thread_id]; + n_pipelines = t->n_pipelines; - /* find pipeline */ for (i = 0; i < n_pipelines; i++) { - struct pipeline_data *p = &t->pipeline_data[i]; + struct rte_swx_pipeline *pipeline = t->pipelines[i]; - if (p->p != pipeline) + if (pipeline != p) continue; if (i < n_pipelines - 1) { - struct rte_swx_pipeline *pipeline_last = - t->p[n_pipelines - 1]; - struct pipeline_data *p_last = - &t->pipeline_data[n_pipelines - 1]; + struct rte_swx_pipeline *pipeline_last = t->pipelines[n_pipelines - 1]; - t->p[i] = pipeline_last; - memcpy(p, p_last, sizeof(*p)); + t->pipelines[i] = pipeline_last; } - t->n_pipelines--; + rte_wmb(); + t->n_pipelines = n_pipelines - 1; - rsp->status = 0; - return rsp; + return; } - /* should not get here */ - rsp->status = 0; - return rsp; -} - -static void -thread_msg_handle(struct thread_data *t) -{ - for ( ; ; ) { - struct thread_msg_req *req; - struct thread_msg_rsp *rsp; - - req = thread_msg_recv(t->msgq_req); - if (req == NULL) - break; - - switch (req->type) { - case THREAD_REQ_PIPELINE_ENABLE: - rsp = thread_msg_handle_pipeline_enable(t, req); - break; - - case THREAD_REQ_PIPELINE_DISABLE: - rsp = thread_msg_handle_pipeline_disable(t, req); - break; - - default: - rsp = (struct thread_msg_rsp *) req; - rsp->status = -1; - } - - thread_msg_send(t->msgq_rsp, rsp); - } + return; } /** - * Data plane threads: main + * Data plane (DP) threads. + * + * The t->n_pipelines variable is modified by the CP thread every time changes to the t->pipeline[] + * array are operated, so it is therefore very important that the latest value of t->n_pipelines is + * read by the DP thread at the beginning of every new dispatch loop iteration, otherwise a stale + * t->n_pipelines value may result in new pipelines not being detected, running pipelines that have + * been removed and are possibly no longer valid (e.g. when the pipeline_last is removed), running + * one pipeline (pipeline_last) twice as frequently than the rest of the pipelines (e.g. when a + * pipeline other than pipeline_last is removed), etc. This is the reason why t->n_pipelines is + * marked as volatile. */ int thread_main(void *arg __rte_unused) { - struct thread_data *t; - uint32_t thread_id, i; + struct thread *t; + uint32_t thread_id; thread_id = rte_lcore_id(); - t = &thread_data[thread_id]; - - /* Dispatch loop */ - for (i = 0; ; i++) { - uint32_t j; - - /* Data Plane */ - for (j = 0; j < t->n_pipelines; j++) - rte_swx_pipeline_run(t->p[j], PIPELINE_INSTR_QUANTA); + t = &threads[thread_id]; - /* Control Plane */ - if ((i & 0xF) == 0) { - uint64_t time = rte_get_tsc_cycles(); - uint64_t time_next_min = UINT64_MAX; - - if (time < t->time_next_min) - continue; - - /* Thread message queues */ - { - uint64_t time_next = t->time_next; - - if (time_next <= time) { - thread_msg_handle(t); - time_next = time + t->timer_period; - t->time_next = time_next; - } - - if (time_next < time_next_min) - time_next_min = time_next; - } + /* Dispatch loop. */ + for ( ; ; ) { + uint32_t i; - t->time_next_min = time_next_min; - } + /* Pipelines. */ + for (i = 0; i < t->n_pipelines; i++) + rte_swx_pipeline_run(t->pipelines[i], PIPELINE_INSTR_QUANTA); } return 0; diff --git a/examples/pipeline/thread.h b/examples/pipeline/thread.h index 712cb25bbb..338d480abb 100644 --- a/examples/pipeline/thread.h +++ b/examples/pipeline/thread.h @@ -9,18 +9,21 @@ #include +/** + * Control plane (CP) thread. + */ int -thread_pipeline_enable(uint32_t thread_id, - struct rte_swx_pipeline *p, - uint32_t timer_period_ms); +thread_init(void); int -thread_pipeline_disable(uint32_t thread_id, - struct rte_swx_pipeline *p); +pipeline_enable(struct rte_swx_pipeline *p, uint32_t thread_id); -int -thread_init(void); +void +pipeline_disable(struct rte_swx_pipeline *p); +/** + * Data plane (DP) threads. + */ int thread_main(void *arg); From patchwork Wed Jan 11 20:56:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121851 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A7D4A423AF; Wed, 11 Jan 2023 21:57:13 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1A8B042D5F; Wed, 11 Jan 2023 21:56:24 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 6CF8C42D55 for ; Wed, 11 Jan 2023 21:56:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470581; x=1705006581; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UP9jTOqMxRhx6NfOBL87d91uIW5MojZg8iAoGgb2WKU=; b=NkWypUxOQcqdemaDXud1VvM70r+u7cqnDRfPF2RI1VlU+17kTHp2MHrd 39C/tp5S1AGuqnQrcVJBPIcAXsgQ9qU5lSpIPWDCN39Fj33zDlf6aQoR1 OvQCv/GQkxvbENt1oUqXi7TU4Xdch4o+SzPPaFQ5xKMTIAutaz8c52s+m i3RB2zBMZnm8MDn0r5EPtMGdigwmDzfjuZtAeoBiolSNGE2dRc0sfp07v P/3KCE7y99IDg+ipma8k8O2dfTxC8TKSraq1zPwYLyIyFs66hagtPhMdj jMTxxyeN6h6o6YEv8bqEdFN1N+IW8xmQjJTEDCNWLyErQHb7twlwbquo6 w==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229795" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229795" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:20 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518898" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518898" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:19 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 09/11] examples/pipeline: support blocks other than pipelines Date: Wed, 11 Jan 2023 20:56:06 +0000 Message-Id: <20230111205608.87953-10-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Previously, the data plane threads only supported the execution of pipelines assigned to them through configuration updates. Now, the data plane threads also support running blocks such as IPsec. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/thread.c | 145 +++++++++++++++++++++++++++++++++++++ examples/pipeline/thread.h | 9 +++ 2 files changed, 154 insertions(+) diff --git a/examples/pipeline/thread.c b/examples/pipeline/thread.c index 3001bc0858..51d6d06a8b 100644 --- a/examples/pipeline/thread.c +++ b/examples/pipeline/thread.c @@ -16,6 +16,10 @@ #define THREAD_PIPELINES_MAX 256 #endif +#ifndef THREAD_BLOCKS_MAX +#define THREAD_BLOCKS_MAX 256 +#endif + /* Pipeline instruction quanta: Needs to be big enough to do some meaningful * work, but not too big to avoid starving any other pipelines mapped to the * same thread. For a pipeline that executes 10 instructions per packet, a @@ -38,9 +42,16 @@ * - Read-write by the CP thread; * - Read-only by the DP thread. */ +struct block { + block_run_f block_func; + void *block; +}; + struct thread { struct rte_swx_pipeline *pipelines[THREAD_PIPELINES_MAX]; + struct block *blocks[THREAD_BLOCKS_MAX]; volatile uint64_t n_pipelines; + volatile uint64_t n_blocks; int enabled; } __rte_cache_aligned; @@ -53,14 +64,43 @@ int thread_init(void) { uint32_t thread_id; + int status = 0; RTE_LCORE_FOREACH_WORKER(thread_id) { struct thread *t = &threads[thread_id]; + uint32_t i; t->enabled = 1; + + for (i = 0; i < THREAD_BLOCKS_MAX; i++) { + struct block *b; + + b = calloc(1, sizeof(struct block)); + if (!b) { + status = -ENOMEM; + goto error; + } + + t->blocks[i] = b; + } } return 0; + +error: + RTE_LCORE_FOREACH_WORKER(thread_id) { + struct thread *t = &threads[thread_id]; + uint32_t i; + + t->enabled = 0; + + for (i = 0; i < THREAD_BLOCKS_MAX; i++) { + free(t->blocks[i]); + t->blocks[i] = NULL; + } + } + + return status; } static uint32_t @@ -83,6 +123,26 @@ pipeline_find(struct rte_swx_pipeline *p) return thread_id; } +static uint32_t +block_find(void *b) +{ + uint32_t thread_id; + + for (thread_id = 0; thread_id < RTE_MAX_LCORE; thread_id++) { + struct thread *t = &threads[thread_id]; + uint32_t i; + + if (!t->enabled) + continue; + + for (i = 0; i < t->n_blocks; i++) + if (t->blocks[i]->block == b) + break; + } + + return thread_id; +} + /** * Enable a given pipeline to run on a specific DP thread. * @@ -201,9 +261,87 @@ pipeline_disable(struct rte_swx_pipeline *p) return; } +int +block_enable(block_run_f block_func, void *block, uint32_t thread_id) +{ + struct thread *t; + uint64_t n_blocks; + + /* Check input params */ + if (!block_func || !block || thread_id >= RTE_MAX_LCORE) + return -EINVAL; + + if (block_find(block) < RTE_MAX_LCORE) + return -EEXIST; + + t = &threads[thread_id]; + if (!t->enabled) + return -EINVAL; + + n_blocks = t->n_blocks; + + /* Check there is room for at least one more block. */ + if (n_blocks >= THREAD_BLOCKS_MAX) + return -ENOSPC; + + /* Install the new block. */ + t->blocks[n_blocks]->block_func = block_func; + t->blocks[n_blocks]->block = block; + + rte_wmb(); + t->n_blocks = n_blocks + 1; + + return 0; +} + +void +block_disable(void *block) +{ + struct thread *t; + uint64_t n_blocks; + uint32_t thread_id, i; + + /* Check input params */ + if (!block) + return; + + /* Find the thread that runs this block. */ + thread_id = block_find(block); + if (thread_id == RTE_MAX_LCORE) + return; + + t = &threads[thread_id]; + n_blocks = t->n_blocks; + + for (i = 0; i < n_blocks; i++) { + struct block *b = t->blocks[i]; + + if (block != b->block) + continue; + + if (i < n_blocks - 1) { + struct block *block_last = t->blocks[n_blocks - 1]; + + t->blocks[i] = block_last; + } + + rte_wmb(); + t->n_blocks = n_blocks - 1; + + rte_wmb(); + t->blocks[n_blocks - 1] = b; + + return; + } + + return; +} + /** * Data plane (DP) threads. * + + * The t->n_pipelines variable is modified by the CP thread every time changes to the t->pipeline[] * array are operated, so it is therefore very important that the latest value of t->n_pipelines is * read by the DP thread at the beginning of every new dispatch loop iteration, otherwise a stale @@ -229,6 +367,13 @@ thread_main(void *arg __rte_unused) /* Pipelines. */ for (i = 0; i < t->n_pipelines; i++) rte_swx_pipeline_run(t->pipelines[i], PIPELINE_INSTR_QUANTA); + + /* Blocks. */ + for (i = 0; i < t->n_blocks; i++) { + struct block *b = t->blocks[i]; + + b->block_func(b->block); + } } return 0; diff --git a/examples/pipeline/thread.h b/examples/pipeline/thread.h index 338d480abb..f2e643def5 100644 --- a/examples/pipeline/thread.h +++ b/examples/pipeline/thread.h @@ -21,6 +21,15 @@ pipeline_enable(struct rte_swx_pipeline *p, uint32_t thread_id); void pipeline_disable(struct rte_swx_pipeline *p); +typedef void +(*block_run_f)(void *block); + +int +block_enable(block_run_f block_func, void *block, uint32_t thread_id); + +void +block_disable(void *block); + /** * Data plane (DP) threads. */ From patchwork Wed Jan 11 20:56:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121852 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 96471423AF; Wed, 11 Jan 2023 21:57:20 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6215A42D6B; Wed, 11 Jan 2023 21:56:25 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id BC46F42D49 for ; Wed, 11 Jan 2023 21:56:22 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470582; x=1705006582; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=faaMpiWMBino5DScWfMbwJ05dbKLdSRr+WtTAYsuXjA=; b=DJwMLk1ruppTHPtMUJ2dTzxkatX8h0LvbmDmi7yPCW3lt/xwZ/1RpxgI EYVSjUdRAxoVzgKsZaU32bjI8sFtFMrZOWmnljbQ16Ag1kodzuCM6Iwxm BdXqmYXIBIRlLGi6C95nCwmNQohtmJNf4a+JZBJ8sxNwrF0i2v/deojUg ajTvqVqcq1mVfbSmzTG2FE7+aTY4NyooXbflrEMQeZzdjy3FI4ecHLGP6 mPOUPPDmB9TwmNqrTT1XGGFgb24b0hpEGZetZppZc67qkogUJkppBHZGJ KOZvha6BTjohz0lSorB4n6oZvlnfB1TEdj4XD6Ohutxu8MUAClPMQzCUI Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229799" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229799" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518903" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518903" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:20 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 10/11] examples/pipeline: add block enable/disable CLI commands Date: Wed, 11 Jan 2023 20:56:07 +0000 Message-Id: <20230111205608.87953-11-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add CLI commands to enable/disable block execution on data plane threads. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/cli.c | 154 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c index d48cbb6240..fad855e1dd 100644 --- a/examples/pipeline/cli.c +++ b/examples/pipeline/cli.c @@ -3249,6 +3249,134 @@ cmd_pipeline_disable(char **tokens, pipeline_disable(p); } +static const char cmd_block_enable_help[] = +"block type instance enable thread \n"; + +static void +cmd_block_enable(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj __rte_unused) +{ + char *block_type, *block_name; + block_run_f block_func = NULL; + void *block = NULL; + uint32_t thread_id; + int status; + + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (strcmp(tokens[1], "type") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "type"); + return; + } + + block_type = tokens[2]; + + if (strcmp(tokens[3], "instance") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "instance"); + return; + } + + block_name = tokens[4]; + + if (strcmp(tokens[5], "enable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); + return; + } + + if (strcmp(tokens[6], "thread") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread"); + return; + } + + if (parser_read_uint32(&thread_id, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); + return; + } + + if (!strcmp(block_type, "ipsec")) { + struct rte_swx_ipsec *ipsec; + + ipsec = rte_swx_ipsec_find(block_name); + if (!ipsec) { + snprintf(out, out_size, MSG_ARG_INVALID, "block_name"); + return; + } + + block_func = (block_run_f)rte_swx_ipsec_run; + block = (void *)ipsec; + } else { + snprintf(out, out_size, MSG_ARG_INVALID, "block_type"); + return; + } + + status = block_enable(block_func, block, thread_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, "block enable"); + return; + } +} + +static const char cmd_block_disable_help[] = +"block type instance disable\n"; + +static void +cmd_block_disable(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj __rte_unused) +{ + char *block_type, *block_name; + void *block = NULL; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (strcmp(tokens[1], "type") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "type"); + return; + } + + block_type = tokens[2]; + + if (strcmp(tokens[3], "instance") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "instance"); + return; + } + + block_name = tokens[4]; + + if (strcmp(tokens[5], "disable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); + return; + } + + if (!strcmp(block_type, "ipsec")) { + struct rte_swx_ipsec *ipsec; + + ipsec = rte_swx_ipsec_find(block_name); + if (!ipsec) { + snprintf(out, out_size, MSG_ARG_INVALID, "block_name"); + return; + } + + block = (void *)ipsec; + } else { + snprintf(out, out_size, MSG_ARG_INVALID, "block_type"); + return; + } + + block_disable(block); +} + static void cmd_help(char **tokens, uint32_t n_tokens, @@ -3297,6 +3425,8 @@ cmd_help(char **tokens, "\tipsec create\n" "\tipsec sa add\n" "\tipsec sa delete\n" + "\tblock enable\n" + "\tblock disable\n" ); return; } @@ -3552,6 +3682,18 @@ cmd_help(char **tokens, return; } + if (!strcmp(tokens[0], "block") && + (n_tokens == 2) && !strcmp(tokens[1], "enable")) { + snprintf(out, out_size, "\n%s\n", cmd_block_enable_help); + return; + } + + if (!strcmp(tokens[0], "block") && + (n_tokens == 2) && !strcmp(tokens[1], "disable")) { + snprintf(out, out_size, "\n%s\n", cmd_block_disable_help); + return; + } + snprintf(out, out_size, "Invalid command\n"); } @@ -3811,6 +3953,18 @@ cli_process(char *in, char *out, size_t out_size, void *obj) } } + if (!strcmp(tokens[0], "block")) { + if (n_tokens >= 6 && !strcmp(tokens[5], "enable")) { + cmd_block_enable(tokens, n_tokens, out, out_size, obj); + return; + } + + if (n_tokens >= 6 && !strcmp(tokens[5], "disable")) { + cmd_block_disable(tokens, n_tokens, out, out_size, obj); + return; + } + } + snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); } From patchwork Wed Jan 11 20:56:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 121853 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0B415423AF; Wed, 11 Jan 2023 21:57:26 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4B1F242D6E; Wed, 11 Jan 2023 21:56:26 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 2186542D60 for ; Wed, 11 Jan 2023 21:56:23 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673470584; x=1705006584; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=k9Xp7VeH11anQvoUkTVDiKTmRP3BCARjXMjpmOwnLVA=; b=JOk4U/ai9v65bBFgQGJdv0/caB6qeyMWj4C3okZYRi0W4AkVgf9QC3Ol MuwPmthTWMOmqMEEgUQap1jt9eeq0DUNdTLfieiZiT50tF39KgFnLOmYz DxVs/dwUwlRIS8+6xiqKE+sdb8tgtFYNYV/l4r0GKof8tGHpUp1LoZ340 oVgxS4JbimKfSGMUYZEK+D8xkDpxpl5Nf8IPGQH13MOwyyxtyoTaJN/Al Ua4grT+fu/goOxRv8T8OFFTY3ZDlsE+7B9HIkcUp1ouie6+gTR3eS4o+6 eMz5ALFU/RtCzbsjFtZfHotVX/NtBLf8Ng5/sZlbFbBXEsVDE/tJk76cN w==; X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="303229802" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="303229802" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2023 12:56:23 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10586"; a="607518913" X-IronPort-AV: E=Sophos;i="5.96,317,1665471600"; d="scan'208";a="607518913" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.222.53]) by orsmga003.jf.intel.com with ESMTP; 11 Jan 2023 12:56:21 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH 11/11] examples/pipeline: add IPsec example Date: Wed, 11 Jan 2023 20:56:08 +0000 Message-Id: <20230111205608.87953-12-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230111205608.87953-1-cristian.dumitrescu@intel.com> References: <20230111205608.87953-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add example files to illustrate the pipeline IPsec support. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- examples/pipeline/examples/ipsec.cli | 57 +++++++ examples/pipeline/examples/ipsec.io | 23 +++ examples/pipeline/examples/ipsec.spec | 138 +++++++++++++++ examples/pipeline/examples/ipsec_sa.txt | 216 ++++++++++++++++++++++++ 4 files changed, 434 insertions(+) create mode 100644 examples/pipeline/examples/ipsec.cli create mode 100644 examples/pipeline/examples/ipsec.io create mode 100644 examples/pipeline/examples/ipsec.spec create mode 100644 examples/pipeline/examples/ipsec_sa.txt diff --git a/examples/pipeline/examples/ipsec.cli b/examples/pipeline/examples/ipsec.cli new file mode 100644 index 0000000000..8cb5bf4239 --- /dev/null +++ b/examples/pipeline/examples/ipsec.cli @@ -0,0 +1,57 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2022 Intel Corporation + +# Example command line: +# ./build/examples/dpdk-pipeline -l0-1 --vdev crypto_aesni_mb0 -- -s ./examples/pipeline/examples/ipsec.cli +# +# Once the application has started, the command to get the CLI prompt is: +# telnet 0.0.0.0 8086 + +; +; Pipeline code generation & shared object library build. +; +pipeline codegen ./examples/pipeline/examples/ipsec.spec /tmp/ipsec.c +pipeline libbuild /tmp/ipsec.c /tmp/ipsec.so + +; +; List of DPDK devices. +; +; Note: Customize the parameters below to match your setup. +; +mempool MEMPOOL0 meta 128 pkt 2176 pool 32K cache 256 numa 0 +ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on +ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on + +cryptodev crypto_aesni_mb0 queues 1 qsize 128 +ring RING0 size 1024 numa 0 +ring RING1 size 1024 numa 0 + +; +; List of pipelines. +; +pipeline PIPELINE0 build lib /tmp/ipsec.so io ./examples/pipeline/examples/ipsec.io numa 0 + +; +; List of IPsec devices. +; +ipsec IPSEC0 create in RING0 out RING1 cryptodev crypto_aesni_mb0 cryptoq 0 bsz 32 32 32 32 samax 512 numa 0 + +; +; Initial set of table entries. +; +; The table entries can later be updated at run-time through the CLI commands. +; +//pipeline PIPELINE0 table policy_table add ./examples/pipeline/examples/ipsec_policy_table.txt +//pipeline PIPELINE0 table routing_table add ./examples/pipeline/examples/ipsec_routing_table.txt +//pipeline PIPELINE0 table nexthop_table add ./examples/pipeline/examples/ipsec_nexthop_table.txt +//pipeline PIPELINE0 commit + +ipsec IPSEC0 sa add ./examples/pipeline/examples/ipsec_sa.txt + +; +; Pipelines and blocks mapping to CPU threads. +; +pipeline PIPELINE0 enable thread 1 +block type ipsec instance IPSEC0 enable thread 1 diff --git a/examples/pipeline/examples/ipsec.io b/examples/pipeline/examples/ipsec.io new file mode 100644 index 0000000000..f5a3fcf961 --- /dev/null +++ b/examples/pipeline/examples/ipsec.io @@ -0,0 +1,23 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2022 Intel Corporation + +; +; Pipeline packet mirroring. +; +mirroring slots 4 sessions 64 + +; +; Pipeline input ports. +; +; Note: Customize the parameters below to match your setup. +; +port in 0 ethdev 0000:18:00.0 rxq 0 bsz 32 +port in 1 ring RING1 bsz 32 + +; +; Pipeline output ports. +; +; Note: Customize the parameters below to match your setup. +; +port out 0 ethdev 0000:18:00.0 txq 0 bsz 32 +port out 1 ring RING0 bsz 32 diff --git a/examples/pipeline/examples/ipsec.spec b/examples/pipeline/examples/ipsec.spec new file mode 100644 index 0000000000..376d9f9334 --- /dev/null +++ b/examples/pipeline/examples/ipsec.spec @@ -0,0 +1,138 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2020 Intel Corporation + +// +// Headers +// +struct ethernet_h { + bit<48> dst_addr + bit<48> src_addr + bit<16> ethertype +} + +struct ipv4_h { + bit<8> ver_ihl + bit<8> diffserv + bit<16> total_len + bit<16> identification + bit<16> flags_offset + bit<8> ttl + bit<8> protocol + bit<16> hdr_checksum + bit<32> src_addr + bit<32> dst_addr +} + +struct udp_h { + bit<16> src_port + bit<16> dst_port + bit<16> length + bit<16> checksum +} + +struct ipsec_internal_h { + bit<32> sa_id +} + +header ethernet instanceof ethernet_h +header ipv4 instanceof ipv4_h +header udp instanceof udp_h +header ipsec_internal instanceof ipsec_internal_h + +// +// Meta-data +// +struct metadata_t { + bit<32> port_in + bit<32> port_out + + bit<32> src_addr + bit<32> dst_addr + bit<8> protocol + bit<16> src_port + bit<16> dst_port +} + +metadata instanceof metadata_t + +// +// Actions +// +struct encrypt_args_t { + bit<32> sa_id +} + +action encrypt args instanceof encrypt_args_t { + //Set the IPsec internal header. + validate h.ipsec_internal + mov h.ipsec_internal.sa_id t.sa_id + + return +} + +action drop args none { + drop +} + +// +// Tables. +// +table policy_table { + key { + m.src_addr exact + m.dst_addr exact + m.protocol exact + m.src_port exact + m.dst_port exact + } + + actions { + encrypt + drop + } + + default_action encrypt args sa_id 0 + size 65536 +} + +// +// Pipeline. +// +apply { + rx m.port_in + + jmpeq FROM_IPSEC_TO_NET m.port_in 1 + +FROM_NET_TO_IPSEC : extract h.ethernet + + extract h.ipv4 + mov m.src_addr h.ipv4.src_addr + mov m.dst_addr h.ipv4.dst_addr + mov m.protocol h.ipv4.protocol + + extract h.udp + mov m.src_port h.udp.src_port + mov m.dst_port h.udp.dst_port + + table policy_table + + mov m.port_out 1 + + emit h.ipsec_internal + emit h.ipv4 + emit h.udp + tx m.port_out + +FROM_IPSEC_TO_NET : extract h.ipv4 + + validate h.ethernet + mov h.ethernet.dst_addr 0xa0b0c0d0e0f0 + mov h.ethernet.src_addr 0xa1b1c1d1e1f1 + mov h.ethernet.ethertype 0x0800 + + mov m.port_out 0 + + emit h.ethernet + emit h.ipv4 + tx m.port_out +} diff --git a/examples/pipeline/examples/ipsec_sa.txt b/examples/pipeline/examples/ipsec_sa.txt new file mode 100644 index 0000000000..37bfd8a9ce --- /dev/null +++ b/examples/pipeline/examples/ipsec_sa.txt @@ -0,0 +1,216 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2022 Intel Corporation + +// IPsec SA syntax: +// +// +// : encrypt +// | decrypt +// ; +// +// +// : +// | +// ; +// +// +// : cipher key +// | cipher +// ; +// +// +// : auth key +// | auth +// ; +// +// +// : aead key +// ; +// +// +// : esp spi tunnel ipv4 srcaddr dstaddr +// | esp spi tunnel ipv6 srcaddr dstaddr +// | esp spi transport +// ; + +// +// cipher = null, auth = null +// +encrypt cipher null auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher null auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher null auth null esp spi 100 transport +decrypt cipher null auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher null auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher null auth null esp spi 100 transport + +// +// aes-gcm-128 +// +encrypt aead aes-gcm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt aead aes-gcm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt aead aes-gcm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 transport +decrypt aead aes-gcm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt aead aes-gcm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt aead aes-gcm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 transport + +// +// aes-gcm-192 +// +encrypt aead aes-gcm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt aead aes-gcm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt aead aes-gcm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 transport +decrypt aead aes-gcm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt aead aes-gcm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt aead aes-gcm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 transport + +// +// aes-gcm-256 +// +encrypt aead aes-gcm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt aead aes-gcm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt aead aes-gcm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 transport +decrypt aead aes-gcm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt aead aes-gcm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt aead aes-gcm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 transport + +// +// aes-ccm-128 +// +encrypt aead aes-ccm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt aead aes-ccm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt aead aes-ccm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 transport +decrypt aead aes-ccm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt aead aes-ccm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt aead aes-ccm-128 key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 transport + +// +// aes-ccm-192 +// +// Note: Currently not supported by the "aesni_mb" library. +// +;encrypt aead aes-ccm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +;encrypt aead aes-ccm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +;encrypt aead aes-ccm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 transport +;decrypt aead aes-ccm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +;decrypt aead aes-ccm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +;decrypt aead aes-ccm-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b esp spi 100 transport + +// +// aes-ccm-256 +// +encrypt aead aes-ccm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt aead aes-ccm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt aead aes-ccm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 transport +decrypt aead aes-ccm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt aead aes-ccm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt aead aes-ccm-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 transport + +// +// chacha20-poly1305 +// +encrypt aead chacha20-poly1305 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt aead chacha20-poly1305 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt aead chacha20-poly1305 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 transport +decrypt aead chacha20-poly1305 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt aead chacha20-poly1305 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt aead chacha20-poly1305 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 esp spi 100 transport + +// +// cipher = aes-cbc-128, auth = null +// +encrypt cipher aes-cbc-128 key 0x000102030405060708090a0b0c0d0e0f auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher aes-cbc-128 key 0x000102030405060708090a0b0c0d0e0f auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher aes-cbc-128 key 0x000102030405060708090a0b0c0d0e0f auth null esp spi 100 transport +decrypt cipher aes-cbc-128 key 0x000102030405060708090a0b0c0d0e0f auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher aes-cbc-128 key 0x000102030405060708090a0b0c0d0e0f auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher aes-cbc-128 key 0x000102030405060708090a0b0c0d0e0f auth null esp spi 100 transport + +// +// cipher = aes-cbc-192, auth = null +// +encrypt cipher aes-cbc-192 key 0x000102030405060708090a0b0c0d0e0f1011121314151617 auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher aes-cbc-192 key 0x000102030405060708090a0b0c0d0e0f1011121314151617 auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher aes-cbc-192 key 0x000102030405060708090a0b0c0d0e0f1011121314151617 auth null esp spi 100 transport +decrypt cipher aes-cbc-192 key 0x000102030405060708090a0b0c0d0e0f1011121314151617 auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher aes-cbc-192 key 0x000102030405060708090a0b0c0d0e0f1011121314151617 auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher aes-cbc-192 key 0x000102030405060708090a0b0c0d0e0f1011121314151617 auth null esp spi 100 transport + +// +// cipher = aes-cbc-256, auth = null +// +encrypt cipher aes-cbc-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher aes-cbc-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher aes-cbc-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f auth null esp spi 100 transport +decrypt cipher aes-cbc-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher aes-cbc-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher aes-cbc-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f auth null esp spi 100 transport + +// +// cipher = aes-ctr-128, auth = null +// +encrypt cipher aes-ctr-128 key 0x000102030405060708090a0b0c0d0e0f10111213 auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher aes-ctr-128 key 0x000102030405060708090a0b0c0d0e0f10111213 auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher aes-ctr-128 key 0x000102030405060708090a0b0c0d0e0f10111213 auth null esp spi 100 transport +decrypt cipher aes-ctr-128 key 0x000102030405060708090a0b0c0d0e0f10111213 auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher aes-ctr-128 key 0x000102030405060708090a0b0c0d0e0f10111213 auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher aes-ctr-128 key 0x000102030405060708090a0b0c0d0e0f10111213 auth null esp spi 100 transport + +// +// cipher = aes-ctr-192, auth = null +// +encrypt cipher aes-ctr-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher aes-ctr-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher aes-ctr-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b auth null esp spi 100 transport +decrypt cipher aes-ctr-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher aes-ctr-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher aes-ctr-192 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b auth null esp spi 100 transport + +// +// cipher = aes-ctr-256, auth = null +// +encrypt cipher aes-ctr-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher aes-ctr-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher aes-ctr-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 auth null esp spi 100 transport +decrypt cipher aes-ctr-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 auth null esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher aes-ctr-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 auth null esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher aes-ctr-256 key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223 auth null esp spi 100 transport + +// +// cipher = null, auth = sha1-hmac +// +encrypt cipher null auth sha1-hmac key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher null auth sha1-hmac key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher null auth sha1-hmac key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 transport +decrypt cipher null auth sha1-hmac key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher null auth sha1-hmac key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher null auth sha1-hmac key 0x000102030405060708090a0b0c0d0e0f10111213 esp spi 100 transport + +// +// cipher = null, auth = sha256-hmac +// +encrypt cipher null auth sha256-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher null auth sha256-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher null auth sha256-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f esp spi 100 transport +decrypt cipher null auth sha256-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher null auth sha256-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher null auth sha256-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f esp spi 100 transport + +// +// cipher = null, auth = sha384-hmac +// +encrypt cipher null auth sha384-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher null auth sha384-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher null auth sha384-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f esp spi 100 transport +decrypt cipher null auth sha384-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher null auth sha384-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher null auth sha384-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f esp spi 100 transport + +// +// cipher = null, auth = sha512-hmac +// +encrypt cipher null auth sha512-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +encrypt cipher null auth sha512-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +encrypt cipher null auth sha512-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f esp spi 100 transport +decrypt cipher null auth sha512-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f esp spi 100 tunnel ipv4 srcaddr 0xa0a1a2a3 dstaddr 0xb0b1b2b3 +decrypt cipher null auth sha512-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f esp spi 100 tunnel ipv6 srcaddr 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf dstaddr b0b1b2b3b4b5b6b7b8b9babbbcbdbebf +decrypt cipher null auth sha512-hmac key 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f esp spi 100 transport