From patchwork Mon Aug 29 15:12:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rahul Bhansali X-Patchwork-Id: 115600 X-Patchwork-Delegate: gakhil@marvell.com 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 64BDBA0542; Mon, 29 Aug 2022 17:12:46 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 50D884069D; Mon, 29 Aug 2022 17:12:46 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 96C0A4003C for ; Mon, 29 Aug 2022 17:12:44 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27T7PpPf029751; Mon, 29 Aug 2022 08:12:43 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=s4FDNym8qZitoul8LtVTog0c71xar4jGCszJUZygslc=; b=b+G7PnIozoViNqObGrPFId6Q4OsEFrQiZGQgugc2Tlr79krEpaIFPHAdfuiJeCtykZEc n4z0nvn5sLj0YWcQrdmfpNhd4fQbGBXOZrNYRGt7McQD9t0Qm5plddqllL+WeAN9MELm Xp8gBOX4q6AFQKkFYEaP0ZaQ5fAabcHOi0rRbLlp7NKp7XhLizOidubD3vS2C5OXt8yB blHikqM+0HQ/aoexyTcRPv2qbZQPQd46QLxjB65QQ2Dm6E90NQUXG9Tgdz8w6zxA1KLb WxtPQZVzBDRR7hvy2RIR4zqpNTbBu1D0CXCDrjLqBcvXZM5yCRiyvu7BperV9dAGgjn4 3w== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3j8s2esk3m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Mon, 29 Aug 2022 08:12:43 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 29 Aug 2022 08:12:42 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.18 via Frontend Transport; Mon, 29 Aug 2022 08:12:42 -0700 Received: from localhost.localdomain (unknown [10.28.36.158]) by maili.marvell.com (Postfix) with ESMTP id A75D23F705B; Mon, 29 Aug 2022 08:12:40 -0700 (PDT) From: Rahul Bhansali To: , Radu Nicolau , Akhil Goyal CC: Rahul Bhansali Subject: [PATCH] examples/ipsec-secgw: support for per SA HW reassembly Date: Mon, 29 Aug 2022 20:42:33 +0530 Message-ID: <20220829151233.2515424-1-rbhansali@marvell.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Proofpoint-GUID: 4BQF1bL63YUidGKfDSVIligw-FSqH5kY X-Proofpoint-ORIG-GUID: 4BQF1bL63YUidGKfDSVIligw-FSqH5kY X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-29_07,2022-08-25_01,2022-06-22_01 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 add the support of hardware reassembly per SA basis. In SA rule, new parameter reassembly_en is added to enable HW reassembly per SA. For example: sa in aead_algo aead_key mode ipv4-tunnel src dst type inline-protocol-offload port_id reassembly_en Stats counter frag_dropped will represent the number of fragment drop in case of reassembly failures. Signed-off-by: Rahul Bhansali Acked-by: Akhil Goyal --- doc/guides/sample_app_ug/ipsec_secgw.rst | 12 ++++++- examples/ipsec-secgw/ipsec-secgw.c | 30 ++++++++++++---- examples/ipsec-secgw/ipsec-secgw.h | 44 +++++++++++++++++++++++- examples/ipsec-secgw/ipsec.c | 2 ++ examples/ipsec-secgw/ipsec.h | 4 ++- examples/ipsec-secgw/ipsec_worker.c | 33 +++++++++++++++++- examples/ipsec-secgw/ipsec_worker.h | 5 +++ examples/ipsec-secgw/sa.c | 12 ++++++- 8 files changed, 130 insertions(+), 12 deletions(-) diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst index 07686d2285..2419513f4b 100644 --- a/doc/guides/sample_app_ug/ipsec_secgw.rst +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst @@ -534,7 +534,7 @@ The SA rule syntax is shown as follows: sa - + where each options means: @@ -790,6 +790,16 @@ where each options means: * *esn N* N is the initial ESN value + ```` + + * Option to enable HW reassembly per SA. + + * Optional: Yes, it is disabled by default + + * Syntax: + + * *reassembly_en* + Example SA rules: .. code-block:: console diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c index 8a25b83535..47dd3709e4 100644 --- a/examples/ipsec-secgw/ipsec-secgw.c +++ b/examples/ipsec-secgw/ipsec-secgw.c @@ -274,6 +274,7 @@ static void print_stats_cb(__rte_unused void *param) { uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; + uint64_t total_frag_packets_dropped = 0; float burst_percent, rx_per_call, tx_per_call; unsigned int coreid; @@ -303,6 +304,7 @@ print_stats_cb(__rte_unused void *param) "\nPackets received: %20"PRIu64 "\nPackets sent: %24"PRIu64 "\nPackets dropped: %21"PRIu64 + "\nFrag Packets dropped: %16"PRIu64 "\nBurst percent: %23.2f" "\nPackets per Rx call: %17.2f" "\nPackets per Tx call: %17.2f", @@ -310,21 +312,25 @@ print_stats_cb(__rte_unused void *param) core_statistics[coreid].rx, core_statistics[coreid].tx, core_statistics[coreid].dropped, + core_statistics[coreid].frag_dropped, burst_percent, rx_per_call, tx_per_call); total_packets_dropped += core_statistics[coreid].dropped; + total_frag_packets_dropped += core_statistics[coreid].frag_dropped; total_packets_tx += core_statistics[coreid].tx; total_packets_rx += core_statistics[coreid].rx; } printf("\nAggregate statistics ===============================" "\nTotal packets received: %14"PRIu64 "\nTotal packets sent: %18"PRIu64 - "\nTotal packets dropped: %15"PRIu64, + "\nTotal packets dropped: %15"PRIu64 + "\nTotal frag packets dropped: %10"PRIu64, total_packets_rx, total_packets_tx, - total_packets_dropped); + total_packets_dropped, + total_frag_packets_dropped); printf("\n====================================================\n"); rte_eal_alarm_set(stats_interval * US_PER_S, print_stats_cb, NULL); @@ -1853,7 +1859,8 @@ parse_ptype_cb(uint16_t port __rte_unused, uint16_t queue __rte_unused, } static void -port_init(uint16_t portid, uint64_t req_rx_offloads, uint64_t req_tx_offloads) +port_init(uint16_t portid, uint64_t req_rx_offloads, uint64_t req_tx_offloads, + uint8_t hw_reassembly) { struct rte_eth_dev_info dev_info; struct rte_eth_txconf *txconf; @@ -1863,6 +1870,7 @@ port_init(uint16_t portid, uint64_t req_rx_offloads, uint64_t req_tx_offloads) struct lcore_conf *qconf; struct rte_ether_addr ethaddr; struct rte_eth_conf local_port_conf = port_conf; + struct rte_eth_ip_reassembly_params reass_capa = {0}; int ptype_supported; ret = rte_eth_dev_info_get(portid, &dev_info); @@ -2039,6 +2047,12 @@ port_init(uint16_t portid, uint64_t req_rx_offloads, uint64_t req_tx_offloads) } } + + if (hw_reassembly) { + rte_eth_ip_reassembly_capability_get(portid, &reass_capa); + reass_capa.timeout_ms = frag_ttl_ns; + rte_eth_ip_reassembly_conf_set(portid, &reass_capa); + } printf("\n"); } @@ -2640,6 +2654,7 @@ update_lcore_statistics(struct ipsec_core_statistics *total, uint32_t coreid) total->rx = lcore_stats->rx; total->dropped = lcore_stats->dropped; + total->frag_dropped = lcore_stats->frag_dropped; total->tx = lcore_stats->tx; /* outbound stats */ @@ -2918,6 +2933,7 @@ main(int32_t argc, char **argv) uint16_t portid, nb_crypto_qp, nb_ports = 0; uint64_t req_rx_offloads[RTE_MAX_ETHPORTS]; uint64_t req_tx_offloads[RTE_MAX_ETHPORTS]; + uint8_t req_hw_reassembly[RTE_MAX_ETHPORTS]; struct eh_conf *eh_conf = NULL; uint32_t ipv4_cksum_port_mask = 0; size_t sess_sz; @@ -3037,10 +3053,10 @@ main(int32_t argc, char **argv) if ((enabled_port_mask & (1 << portid)) == 0) continue; - sa_check_offloads(portid, &req_rx_offloads[portid], - &req_tx_offloads[portid]); - port_init(portid, req_rx_offloads[portid], - req_tx_offloads[portid]); + sa_check_offloads(portid, &req_rx_offloads[portid], &req_tx_offloads[portid], + &req_hw_reassembly[portid]); + port_init(portid, req_rx_offloads[portid], req_tx_offloads[portid], + req_hw_reassembly[portid]); if ((req_tx_offloads[portid] & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)) ipv4_cksum_port_mask = 1U << portid; } diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h index f02736075b..f761246e73 100644 --- a/examples/ipsec-secgw/ipsec-secgw.h +++ b/examples/ipsec-secgw/ipsec-secgw.h @@ -5,6 +5,7 @@ #define _IPSEC_SECGW_H_ #include +#include #define MAX_RX_QUEUE_PER_LCORE 16 @@ -103,6 +104,7 @@ struct ipsec_core_statistics { uint64_t rx_call; uint64_t tx_call; uint64_t dropped; + uint64_t frag_dropped; uint64_t burst_rx; struct { @@ -142,7 +144,7 @@ extern volatile bool force_quit; extern uint32_t nb_bufs_in_pool; extern bool per_port_pool; - +extern int ip_reassembly_dynfield_offset; extern uint32_t mtu_size; extern uint32_t frag_tbl_sz; @@ -186,6 +188,46 @@ core_stats_update_drop(int n) core_statistics[lcore_id].dropped += n; } +static inline void +core_stats_update_frag_drop(int n) +{ + int lcore_id = rte_lcore_id(); + core_statistics[lcore_id].frag_dropped += n; +} + +extern uint64_t ip_reassembly_dynflag; + +static inline int +is_ip_reassembly_incomplete(struct rte_mbuf *mbuf) +{ + if (ip_reassembly_dynflag == 0) + return -1; + return (mbuf->ol_flags & ip_reassembly_dynflag) != 0; +} + +static inline void +free_reassembly_fail_pkt(struct rte_mbuf *mb) +{ + if (ip_reassembly_dynfield_offset >= 0) { + rte_eth_ip_reassembly_dynfield_t dynfield; + uint32_t frag_cnt = 0; + + while (mb) { + dynfield = *RTE_MBUF_DYNFIELD(mb, + ip_reassembly_dynfield_offset, + rte_eth_ip_reassembly_dynfield_t *); + rte_pktmbuf_free(mb); + mb = dynfield.next_frag; + frag_cnt++; + } + + core_stats_update_frag_drop(frag_cnt); + } else { + rte_pktmbuf_free(mb); + core_stats_update_drop(1); + } +} + /* helper routine to free bulk of packets */ static inline void free_pkts(struct rte_mbuf *mb[], uint32_t n) diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c index 7b7bfff696..ebf6d30fc3 100644 --- a/examples/ipsec-secgw/ipsec.c +++ b/examples/ipsec-secgw/ipsec.c @@ -52,6 +52,8 @@ set_ipsec_conf(struct ipsec_sa *sa, struct rte_security_ipsec_xform *ipsec) ipsec->replay_win_sz = app_sa_prm.window_size; ipsec->options.esn = app_sa_prm.enable_esn; ipsec->options.udp_encap = sa->udp_encap; + if (IS_HW_REASSEMBLY_EN(sa->flags)) + ipsec->options.ip_reassembly_en = 1; } int diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h index 2c37bb022d..fb100db135 100644 --- a/examples/ipsec-secgw/ipsec.h +++ b/examples/ipsec-secgw/ipsec.h @@ -131,6 +131,7 @@ struct ipsec_sa { #define IP4_TRANSPORT (1 << 3) #define IP6_TRANSPORT (1 << 4) #define SA_TELEMETRY_ENABLE (1 << 5) +#define SA_REASSEMBLY_ENABLE (1 << 6) struct ip_addr src; struct ip_addr dst; @@ -207,6 +208,7 @@ struct ipsec_mbuf_metadata { #define IS_IP6_TUNNEL(flags) ((flags) & IP6_TUNNEL) +#define IS_HW_REASSEMBLY_EN(flags) ((flags) & SA_REASSEMBLY_ENABLE) /* * Macro for getting ipsec_sa flags statuses without version of protocol * used for transport (IP4_TRANSPORT and IP6_TRANSPORT flags). @@ -433,7 +435,7 @@ rt_init(struct socket_ctx *ctx, int32_t socket_id); int sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads, - uint64_t *tx_offloads); + uint64_t *tx_offloads, uint8_t *hw_reassembly); int add_dst_ethaddr(uint16_t port, const struct rte_ether_addr *addr); diff --git a/examples/ipsec-secgw/ipsec_worker.c b/examples/ipsec-secgw/ipsec_worker.c index 803157d8ee..0067651f63 100644 --- a/examples/ipsec-secgw/ipsec_worker.c +++ b/examples/ipsec-secgw/ipsec_worker.c @@ -23,6 +23,9 @@ struct port_drv_mode_data { typedef void (*ipsec_worker_fn_t)(void); +int ip_reassembly_dynfield_offset = -1; +uint64_t ip_reassembly_dynflag; + static inline enum pkt_type process_ipsec_get_pkt_type(struct rte_mbuf *pkt, uint8_t **nlp) { @@ -300,6 +303,10 @@ process_ipsec_ev_inbound(struct ipsec_ctx *ctx, struct route_table *rt, /* Get pkt from event */ pkt = ev->mbuf; + if (is_ip_reassembly_incomplete(pkt) > 0) { + free_reassembly_fail_pkt(pkt); + return PKT_DROPPED; + } /* Check the packet type */ type = process_ipsec_get_pkt_type(pkt, &nlp); @@ -381,7 +388,6 @@ process_ipsec_ev_inbound(struct ipsec_ctx *ctx, struct route_table *rt, return PKT_FORWARDED; drop_pkt_and_exit: - RTE_LOG(ERR, IPSEC, "Inbound packet dropped\n"); rte_pktmbuf_free(pkt); ev->mbuf = NULL; return PKT_DROPPED; @@ -604,6 +610,10 @@ process_ipsec_ev_inbound_vector(struct ipsec_ctx *ctx, struct route_table *rt, for (i = 0; i < vec->nb_elem; i++) { /* Get pkt from event */ pkt = vec->mbufs[i]; + if (is_ip_reassembly_incomplete(pkt) > 0) { + free_reassembly_fail_pkt(pkt); + continue; + } if (pkt->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) { if (unlikely(pkt->ol_flags & @@ -753,6 +763,23 @@ ipsec_event_port_flush(uint8_t eventdev_id __rte_unused, struct rte_event ev, /* Workers registered */ #define IPSEC_EVENTMODE_WORKERS 2 +static void +ipsec_ip_reassembly_dyn_offset_get(void) +{ + /* Retrieve reassembly dynfield offset if available */ + if (ip_reassembly_dynfield_offset < 0) + ip_reassembly_dynfield_offset = rte_mbuf_dynfield_lookup( + RTE_MBUF_DYNFIELD_IP_REASSEMBLY_NAME, NULL); + + if (ip_reassembly_dynflag == 0) { + int ip_reassembly_dynflag_offset; + ip_reassembly_dynflag_offset = rte_mbuf_dynflag_lookup( + RTE_MBUF_DYNFLAG_IP_REASSEMBLY_INCOMPLETE_NAME, NULL); + if (ip_reassembly_dynflag_offset >= 0) + ip_reassembly_dynflag = RTE_BIT64(ip_reassembly_dynflag_offset); + } +} + /* * Event mode worker * Operating parameters : non-burst - Tx internal port - driver mode @@ -933,6 +960,8 @@ ipsec_wrkr_non_burst_int_port_app_mode(struct eh_event_link_info *links, RTE_LOG(INFO, IPSEC, " -- lcoreid=%u event_port_id=%u\n", lcore_id, links[0].event_port_id); + ipsec_ip_reassembly_dyn_offset_get(); + while (!force_quit) { /* Read packet from event queues */ nb_rx = rte_event_dequeue_burst(links[0].eventdev_id, @@ -1192,6 +1221,8 @@ ipsec_poll_mode_wrkr_inl_pr(void) lcore_id, portid, queueid); } + ipsec_ip_reassembly_dyn_offset_get(); + while (!force_quit) { cur_tsc = rte_rdtsc(); diff --git a/examples/ipsec-secgw/ipsec_worker.h b/examples/ipsec-secgw/ipsec_worker.h index 9e6d826965..453e93169e 100644 --- a/examples/ipsec-secgw/ipsec_worker.h +++ b/examples/ipsec-secgw/ipsec_worker.h @@ -130,6 +130,11 @@ prepare_one_packet(struct rte_security_ctx *ctx, struct rte_mbuf *pkt, uint64_t tx_offload; uint16_t l3len; + if (is_ip_reassembly_incomplete(pkt) > 0) { + free_reassembly_fail_pkt(pkt); + return; + } + tun_type = ptype & RTE_PTYPE_TUNNEL_MASK; l3_type = ptype & RTE_PTYPE_L3_MASK; diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c index 5dca578790..6fe7c56470 100644 --- a/examples/ipsec-secgw/sa.c +++ b/examples/ipsec-secgw/sa.c @@ -785,6 +785,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens, continue; } + if (strcmp(tokens[ti], "reassembly_en") == 0) { + rule->flags |= SA_REASSEMBLY_ENABLE; + continue; + } + if (strcmp(tokens[ti], "esn") == 0) { INCREMENT_TOKEN_INDEX(ti, n_tokens, status); if (status->status < 0) @@ -1805,7 +1810,7 @@ outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[], */ int sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads, - uint64_t *tx_offloads) + uint64_t *tx_offloads, uint8_t *hw_reassembly) { struct ipsec_sa *rule; uint32_t idx_sa; @@ -1831,6 +1836,11 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads, RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) && rule->portid == port_id) *rx_offloads |= RTE_ETH_RX_OFFLOAD_SECURITY; + if (IS_HW_REASSEMBLY_EN(rule->flags)) { + *rx_offloads |= RTE_ETH_RX_OFFLOAD_SCATTER; + *tx_offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; + *hw_reassembly = 1; + } } /* Check for outbound rules that use offloads and use this port */