From fe2d23f916d1991f4a1a8384eae41b5cceb80189 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Fri, 18 Nov 2022 04:24:09 +0000 Subject: ipsec: Failure at the start of the batch should not invalidate the rest of the batch Type: fix Signed-off-by: Neale Ranns Change-Id: Icd1e43a5764496784c355c93066273435f16dd35 --- src/plugins/crypto_sw_scheduler/main.c | 38 +++++++++++++++++++++------------- src/vnet/ipsec/esp_decrypt.c | 2 +- test/template_ipsec.py | 28 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/plugins/crypto_sw_scheduler/main.c b/src/plugins/crypto_sw_scheduler/main.c index 09d4a0b9b94..991ef6a43f7 100644 --- a/src/plugins/crypto_sw_scheduler/main.c +++ b/src/plugins/crypto_sw_scheduler/main.c @@ -260,17 +260,22 @@ process_ops (vlib_main_t * vm, vnet_crypto_async_frame_t * f, n_fail = n_ops - vnet_crypto_process_ops (vm, op, n_ops); - while (n_fail) + /* + * If we had a failure in the ops then we need to walk all the ops + * and set the status in the corresponding frame. This status is + * not set in the case with no failures, as in that case the overall + * frame status is success. + */ + if (n_fail) { - ASSERT (op - ops < n_ops); - - if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED) + for (int i = 0; i < n_ops; i++) { + ASSERT (op - ops < n_ops); + f->elts[op->user_data].status = op->status; - *state = VNET_CRYPTO_FRAME_STATE_ELT_ERROR; - n_fail--; + op++; } - op++; + *state = VNET_CRYPTO_FRAME_STATE_ELT_ERROR; } } @@ -287,17 +292,22 @@ process_chained_ops (vlib_main_t * vm, vnet_crypto_async_frame_t * f, n_fail = n_ops - vnet_crypto_process_chained_ops (vm, op, chunks, n_ops); - while (n_fail) + /* + * If we had a failure in the ops then we need to walk all the ops + * and set the status in the corresponding frame. This status is + * not set in the case with no failures, as in that case the overall + * frame status is success. + */ + if (n_fail) { - ASSERT (op - ops < n_ops); - - if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED) + for (int i = 0; i < n_ops; i++) { + ASSERT (op - ops < n_ops); + f->elts[op->user_data].status = op->status; - *state = VNET_CRYPTO_FRAME_STATE_ELT_ERROR; - n_fail--; + op++; } - op++; + *state = VNET_CRYPTO_FRAME_STATE_ELT_ERROR; } } diff --git a/src/vnet/ipsec/esp_decrypt.c b/src/vnet/ipsec/esp_decrypt.c index f80b3794f2a..306fb7d2ce6 100644 --- a/src/vnet/ipsec/esp_decrypt.c +++ b/src/vnet/ipsec/esp_decrypt.c @@ -1189,7 +1189,7 @@ esp_decrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node, else esp_decrypt_prepare_sync_op ( vm, node, ptd, &crypto_ops, &integ_ops, op, sa0, payload, len, - cpd.icv_sz, cpd.iv_sz, pd, pd2, b[0], sync_next, b - bufs); + cpd.icv_sz, cpd.iv_sz, pd, pd2, b[0], sync_next, n_sync); /* next */ next: if (ESP_DECRYPT_ERROR_RX_PKTS != err) diff --git a/test/template_ipsec.py b/test/template_ipsec.py index def31cbebbd..9d9ea3a86d3 100644 --- a/test/template_ipsec.py +++ b/test/template_ipsec.py @@ -432,6 +432,34 @@ class IpsecTra4(object): ] recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if) + # a replayed packet, then an out of window, then a legit + # tests that a early failure on the batch doesn't affect subsequent packets. + pkts = [ + ( + Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) + / p.scapy_tra_sa.encrypt( + IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(), + seq_num=203, + ) + ), + ( + Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) + / p.scapy_tra_sa.encrypt( + IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(), + seq_num=81, + ) + ), + ( + Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) + / p.scapy_tra_sa.encrypt( + IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(), + seq_num=204, + ) + ), + ] + n_rx = 1 if ar_on else 3 + recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if, n_rx=n_rx) + # move the window over half way to a wrap pkts = [ ( -- cgit 1.2.3-korg