* [PATCH] examples/ipsec-secgw: support for per SA HW reassembly
@ 2022-08-29 15:12 Rahul Bhansali
2022-10-21 15:57 ` Akhil Goyal
2022-10-27 11:05 ` [PATCH v2] examples/ipsec-secgw: support " Rahul Bhansali
0 siblings, 2 replies; 4+ messages in thread
From: Rahul Bhansali @ 2022-08-29 15:12 UTC (permalink / raw)
To: dev, Radu Nicolau, Akhil Goyal; +Cc: Rahul Bhansali
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 <idx> aead_algo <algo> aead_key <key> mode ipv4-tunnel src <ip>
dst <ip> type inline-protocol-offload port_id <id> reassembly_en
Stats counter frag_dropped will represent the number of fragment
drop in case of reassembly failures.
Signed-off-by: Rahul Bhansali <rbhansali@marvell.com>
---
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 <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>
<mode> <src_ip> <dst_ip> <action_type> <port_id> <fallback>
- <flow-direction> <port_id> <queue_id> <udp-encap>
+ <flow-direction> <port_id> <queue_id> <udp-encap> <reassembly_en>
where each options means:
@@ -790,6 +790,16 @@ where each options means:
* *esn N* N is the initial ESN value
+ ``<reassembly_en>``
+
+ * 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 <stdbool.h>
+#include <rte_ethdev.h>
#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 */
--
2.25.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH] examples/ipsec-secgw: support for per SA HW reassembly
2022-08-29 15:12 [PATCH] examples/ipsec-secgw: support for per SA HW reassembly Rahul Bhansali
@ 2022-10-21 15:57 ` Akhil Goyal
2022-10-27 11:05 ` [PATCH v2] examples/ipsec-secgw: support " Rahul Bhansali
1 sibling, 0 replies; 4+ messages in thread
From: Akhil Goyal @ 2022-10-21 15:57 UTC (permalink / raw)
To: Rahul Bhansali, dev, Radu Nicolau; +Cc: hemant.agrawal, Gagandeep Singh
> @@ -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;
A nit, move this extern next to ip_reassembly_dynfield_offset
Apart from that
Acked-by: Akhil Goyal <gakhil@marvell.com>
Also change the patch title as
examples/ipsec-secgw: support per SA HW reassembly
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] examples/ipsec-secgw: support per SA HW reassembly
2022-08-29 15:12 [PATCH] examples/ipsec-secgw: support for per SA HW reassembly Rahul Bhansali
2022-10-21 15:57 ` Akhil Goyal
@ 2022-10-27 11:05 ` Rahul Bhansali
2022-10-27 14:13 ` Akhil Goyal
1 sibling, 1 reply; 4+ messages in thread
From: Rahul Bhansali @ 2022-10-27 11:05 UTC (permalink / raw)
To: dev, Radu Nicolau, Akhil Goyal; +Cc: Rahul Bhansali
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 <idx> aead_algo <algo> aead_key <key> mode ipv4-tunnel src <ip>
dst <ip> type inline-protocol-offload port_id <id> reassembly_en
Stats counter frag_dropped will represent the number of fragment
drop in case of reassembly failures.
Signed-off-by: Rahul Bhansali <rbhansali@marvell.com>
---
Changes in v2:
- updated patch title, and moved extern of ip_reassembly_dynflag next to
ip_reassembly_dynfield_offset.
doc/guides/sample_app_ug/ipsec_secgw.rst | 12 ++++++-
examples/ipsec-secgw/ipsec-secgw.c | 30 +++++++++++++----
examples/ipsec-secgw/ipsec-secgw.h | 43 +++++++++++++++++++++++-
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, 129 insertions(+), 12 deletions(-)
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 2a1aeae7c5..4d889e8496 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -537,7 +537,7 @@ The SA rule syntax is shown as follows:
sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>
<mode> <src_ip> <dst_ip> <action_type> <port_id> <fallback>
- <flow-direction> <port_id> <queue_id> <udp-encap>
+ <flow-direction> <port_id> <queue_id> <udp-encap> <reassembly_en>
where each options means:
@@ -793,6 +793,16 @@ where each options means:
* *esn N* N is the initial ESN value
+ ``<reassembly_en>``
+
+ * 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 1d9982a786..24d895451a 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);
@@ -1867,7 +1873,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;
@@ -1877,6 +1884,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);
@@ -2053,6 +2061,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");
}
@@ -2598,6 +2612,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 */
@@ -2876,6 +2891,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;
@@ -2993,10 +3009,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 c6d11f3aac..0e0012d058 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -5,6 +5,7 @@
#define _IPSEC_SECGW_H_
#include <stdbool.h>
+#include <rte_ethdev.h>
#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,8 @@ extern volatile bool force_quit;
extern uint32_t nb_bufs_in_pool;
extern bool per_port_pool;
-
+extern int ip_reassembly_dynfield_offset;
+extern uint64_t ip_reassembly_dynflag;
extern uint32_t mtu_size;
extern uint32_t frag_tbl_sz;
extern uint32_t qp_desc_nb;
@@ -187,6 +190,44 @@ 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;
+}
+
+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 d90b59774d..9b52d37b81 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -53,6 +53,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 3d373dfd77..a21402ef5f 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -132,6 +132,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;
@@ -208,6 +209,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).
@@ -434,7 +436,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 2a4f039991..cbb41bc192 100644
--- a/examples/ipsec-secgw/ipsec_worker.c
+++ b/examples/ipsec-secgw/ipsec_worker.c
@@ -25,6 +25,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)
{
@@ -417,6 +420,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);
@@ -526,7 +533,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");
free_pkts(&pkt, 1);
ev->mbuf = NULL;
return PKT_DROPPED;
@@ -859,6 +865,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 &
@@ -1150,6 +1160,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
@@ -1338,6 +1365,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,
@@ -1606,6 +1635,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 ec50d0250a..d5a68d91fa 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 dc3627aacc..7da9444a7b 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -786,6 +786,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)
@@ -1813,7 +1818,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;
@@ -1839,6 +1844,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 */
--
2.25.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH v2] examples/ipsec-secgw: support per SA HW reassembly
2022-10-27 11:05 ` [PATCH v2] examples/ipsec-secgw: support " Rahul Bhansali
@ 2022-10-27 14:13 ` Akhil Goyal
0 siblings, 0 replies; 4+ messages in thread
From: Akhil Goyal @ 2022-10-27 14:13 UTC (permalink / raw)
To: Rahul Bhansali, dev, Radu Nicolau; +Cc: Rahul Bhansali
> Subject: [PATCH v2] examples/ipsec-secgw: support per SA HW reassembly
>
> 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 <idx> aead_algo <algo> aead_key <key> mode ipv4-tunnel src <ip>
> dst <ip> type inline-protocol-offload port_id <id> reassembly_en
>
> Stats counter frag_dropped will represent the number of fragment
> drop in case of reassembly failures.
>
> Signed-off-by: Rahul Bhansali <rbhansali@marvell.com>
> ---
Acked-by: Akhil Goyal <gakhil@marvell.com>
Applied to dpdk-next-crypto
Thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-10-27 14:13 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-29 15:12 [PATCH] examples/ipsec-secgw: support for per SA HW reassembly Rahul Bhansali
2022-10-21 15:57 ` Akhil Goyal
2022-10-27 11:05 ` [PATCH v2] examples/ipsec-secgw: support " Rahul Bhansali
2022-10-27 14:13 ` Akhil Goyal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).