From: Dmitry Eremin-Solenikov <dmitry.ereminsoleni...@linaro.org>

Add new ipsec_err error flag, which is set by IPsec code if there was an
error during IPsec packet processing. This allow application code to
quickly check packets using odp_packet_has_error() function and use fast
path if there was none.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsoleni...@linaro.org>
---
/** Email created from pull request 243 (lumag:ipsec-packet-impl-3)
 ** https://github.com/Linaro/odp/pull/243
 ** Patch: https://github.com/Linaro/odp/pull/243.patch
 ** Base sha: d22c949cc466bf28de559855a1cb525740578137
 ** Merge commit sha: 636bc4f4108f651355ad9bbb9e7820bd9fc754e7
 **/
 .../linux-generic/include/odp_packet_internal.h    |   1 +
 platform/linux-generic/odp_ipsec.c                 | 104 ++++++++++++---------
 2 files changed, 60 insertions(+), 45 deletions(-)

diff --git a/platform/linux-generic/include/odp_packet_internal.h 
b/platform/linux-generic/include/odp_packet_internal.h
index fed562aa3..9c8b48b0c 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -53,6 +53,7 @@ typedef union {
                uint32_t ip_err:1;    /**< IP error,  checks TBD */
                uint32_t tcp_err:1;   /**< TCP error, checks TBD */
                uint32_t udp_err:1;   /**< UDP error, checks TBD */
+               uint32_t ipsec_err:1; /**< IPsec error */
        };
 } error_flags_t;
 
diff --git a/platform/linux-generic/odp_ipsec.c 
b/platform/linux-generic/odp_ipsec.c
index 74a1c5766..8101b00c6 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -286,6 +286,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
        uint8_t  ip_ttl;         /**< Saved IP TTL value */
        uint16_t ip_frag_offset; /**< Saved IP flags value */
        odp_crypto_packet_result_t crypto; /**< Crypto operation result */
+       odp_packet_hdr_t *pkt_hdr;
 
        ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != ip_offset);
        ODP_ASSERT(NULL != ip);
@@ -301,7 +302,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 
        if (_ODP_IPV4HDR_IS_FRAGMENT(odp_be_to_cpu_16(ip->frag_offset))) {
                status->error.proto = 1;
-               goto out;
+               goto err;
        }
 
        /* Check IP header for IPSec protocols and look it up */
@@ -311,7 +312,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                if (odp_packet_copy_to_mem(pkt, ipsec_offset,
                                           sizeof(esp), &esp) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
 
                if (ODP_IPSEC_SA_INVALID == sa) {
@@ -324,7 +325,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                        ipsec_sa = _odp_ipsec_sa_lookup(&lookup);
                        if (NULL == ipsec_sa) {
                                status->error.sa_lookup = 1;
-                               goto out;
+                               goto err;
                        }
                } else {
                        ipsec_sa = _odp_ipsec_sa_use(sa);
@@ -332,7 +333,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                        if (ipsec_sa->proto != ODP_IPSEC_ESP ||
                            ipsec_sa->spi != odp_be_to_cpu_32(esp.spi)) {
                                status->error.proto = 1;
-                               goto out;
+                               goto err;
                        }
                }
 
@@ -342,7 +343,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                                           ipsec_sa->esp_iv_len,
                                           iv + ipsec_sa->salt_length) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
 
                hdr_len = _ODP_ESPHDR_LEN + ipsec_sa->esp_iv_len;
@@ -376,7 +377,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                if (odp_packet_copy_to_mem(pkt, ipsec_offset,
                                           sizeof(ah), &ah) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
 
                if (ODP_IPSEC_SA_INVALID == sa) {
@@ -389,7 +390,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                        ipsec_sa = _odp_ipsec_sa_lookup(&lookup);
                        if (NULL == ipsec_sa) {
                                status->error.sa_lookup = 1;
-                               goto out;
+                               goto err;
                        }
                } else {
                        ipsec_sa = _odp_ipsec_sa_use(sa);
@@ -397,7 +398,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                        if (ipsec_sa->proto != ODP_IPSEC_AH ||
                            ipsec_sa->spi != odp_be_to_cpu_32(ah.spi)) {
                                status->error.proto = 1;
-                               goto out;
+                               goto err;
                        }
                }
 
@@ -431,16 +432,16 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                stats_length = param.auth_range.length;
        } else {
                status->error.proto = 1;
-               goto out;
+               goto err;
        }
 
        if (_odp_ipsec_sa_replay_precheck(ipsec_sa,
                                          odp_be_to_cpu_32(aad.seq_no),
                                          status) < 0)
-               goto out;
+               goto err;
 
        if (_odp_ipsec_sa_stats_precheck(ipsec_sa, status) < 0)
-               goto out;
+               goto err;
 
        param.session = ipsec_sa->session;
 
@@ -448,14 +449,14 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
        if (rc < 0) {
                ODP_DBG("Crypto failed\n");
                status->error.alg = 1;
-               goto out;
+               goto err;
        }
 
        rc = odp_crypto_result(&crypto, pkt);
        if (rc < 0) {
                ODP_DBG("Crypto failed\n");
                status->error.alg = 1;
-               goto out;
+               goto err;
        }
 
        if (!crypto.ok) {
@@ -471,16 +472,16 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                     ODP_CRYPTO_HW_ERR_NONE))
                        status->error.auth = 1;
 
-               goto out;
+               goto err;
        }
 
        if (_odp_ipsec_sa_stats_update(ipsec_sa, stats_length, status) < 0)
-               goto out;
+               goto err;
 
        if (_odp_ipsec_sa_replay_update(ipsec_sa,
                                        odp_be_to_cpu_32(aad.seq_no),
                                        status) < 0)
-               goto out;
+               goto err;
 
        ip_offset = odp_packet_l3_offset(pkt);
        ip = odp_packet_l3_ptr(pkt, NULL);
@@ -498,18 +499,18 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                if (odp_packet_copy_to_mem(pkt, esptrl_offset,
                                           sizeof(esptrl), &esptrl) < 0) {
                        status->error.proto = 1;
-                       goto out;
+                       goto err;
                }
 
                if (ip_offset + esptrl.pad_len > esptrl_offset) {
                        status->error.proto = 1;
-                       goto out;
+                       goto err;
                }
 
                if (_odp_packet_cmp_data(pkt, esptrl_offset - esptrl.pad_len,
                                         ipsec_padding, esptrl.pad_len) != 0) {
                        status->error.proto = 1;
-                       goto out;
+                       goto err;
                }
 
                ip->proto = esptrl.next_header;
@@ -523,7 +524,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                if (odp_packet_copy_to_mem(pkt, ipsec_offset,
                                           sizeof(ah), &ah) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
 
                ip->proto = ah.next_header;
@@ -534,12 +535,12 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                ip->frag_offset = odp_cpu_to_be_16(ip_frag_offset);
        } else {
                status->error.proto = 1;
-               goto out;
+               goto err;
        }
 
        if (odp_packet_trunc_tail(&pkt, trl_len, NULL, NULL) < 0) {
                status->error.alg = 1;
-               goto out;
+               goto err;
        }
 
        if (ODP_IPSEC_MODE_TUNNEL == ipsec_sa->mode) {
@@ -550,7 +551,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                if (odp_packet_trunc_head(&pkt, ip_hdr_len + hdr_len,
                                          NULL, NULL) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
        } else {
                odp_packet_move_data(pkt, hdr_len, 0,
@@ -558,7 +559,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                if (odp_packet_trunc_head(&pkt, hdr_len,
                                          NULL, NULL) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
        }
 
@@ -573,15 +574,21 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
                _odp_ipv4_csum_update(pkt);
        }
 
-       if (!status->error.all) {
-               odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+       pkt_hdr = odp_packet_hdr(pkt);
 
-               packet_parse_reset(pkt_hdr);
+       packet_parse_reset(pkt_hdr);
+
+       packet_parse_l3_l4(pkt_hdr, parse_layer(ipsec_config.inbound.parse),
+                          ip_offset, _ODP_ETHTYPE_IPV4);
+
+       *pkt_out = pkt;
+
+       return ipsec_sa;
+
+err:
+       pkt_hdr = odp_packet_hdr(pkt);
+       pkt_hdr->p.error_flags.ipsec_err = 1;
 
-               packet_parse_l3_l4(pkt_hdr, 
parse_layer(ipsec_config.inbound.parse),
-                                  ip_offset, _ODP_ETHTYPE_IPV4);
-       }
-out:
        *pkt_out = pkt;
 
        return ipsec_sa;
@@ -620,6 +627,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
        uint8_t  ip_ttl;         /**< Saved IP TTL value */
        uint16_t ip_frag_offset; /**< Saved IP flags value */
        odp_crypto_packet_result_t crypto; /**< Crypto operation result */
+       odp_packet_hdr_t *pkt_hdr;
 
        ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != ip_offset);
        ODP_ASSERT(NULL != ip);
@@ -637,7 +645,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
        if (ODP_IPSEC_MODE_TRANSPORT == ipsec_sa->mode &&
            _ODP_IPV4HDR_IS_FRAGMENT(odp_be_to_cpu_16(ip->frag_offset))) {
                status->error.alg = 1;
-               goto out;
+               goto err;
        }
 
        if (ODP_IPSEC_MODE_TUNNEL == ipsec_sa->mode) {
@@ -673,7 +681,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
                if (odp_packet_extend_head(&pkt, _ODP_IPV4HDR_LEN,
                                           NULL, NULL) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
 
                odp_packet_move_data(pkt, 0, _ODP_IPV4HDR_LEN, ip_offset);
@@ -719,7 +727,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
                                                       1);
                        /* Check for overrun */
                        if (ctr == 0)
-                               goto out;
+                               goto err;
 
                        memcpy(iv, ipsec_sa->salt, ipsec_sa->salt_length);
                        memcpy(iv + ipsec_sa->salt_length, &ctr,
@@ -735,7 +743,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 
                        if (len != ipsec_sa->esp_iv_len) {
                                status->error.alg = 1;
-                               goto out;
+                               goto err;
                        }
 
                        memcpy(iv, ipsec_sa->salt, ipsec_sa->salt_length);
@@ -745,12 +753,12 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 
                if (odp_packet_extend_tail(&pkt, trl_len, NULL, NULL) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
 
                if (odp_packet_extend_head(&pkt, hdr_len, NULL, NULL) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
 
                odp_packet_move_data(pkt, 0, hdr_len, ipsec_offset);
@@ -824,12 +832,12 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 
                if (odp_packet_extend_tail(&pkt, trl_len, NULL, NULL) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
 
                if (odp_packet_extend_head(&pkt, hdr_len, NULL, NULL) < 0) {
                        status->error.alg = 1;
-                       goto out;
+                       goto err;
                }
 
                odp_packet_move_data(pkt, 0, hdr_len, ipsec_offset);
@@ -871,12 +879,12 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
                stats_length = param.auth_range.length;
        } else {
                status->error.alg = 1;
-               goto out;
+               goto err;
        }
 
        /* No need to run precheck here, we know that packet is authentic */
        if (_odp_ipsec_sa_stats_update(ipsec_sa, stats_length, status) < 0)
-               goto out;
+               goto err;
 
        param.session = ipsec_sa->session;
 
@@ -884,14 +892,14 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
        if (rc < 0) {
                ODP_DBG("Crypto failed\n");
                status->error.alg = 1;
-               goto out;
+               goto err;
        }
 
        rc = odp_crypto_result(&crypto, pkt);
        if (rc < 0) {
                ODP_DBG("Crypto failed\n");
                status->error.alg = 1;
-               goto out;
+               goto err;
        }
 
        if (!crypto.ok) {
@@ -907,7 +915,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
                     ODP_CRYPTO_HW_ERR_NONE))
                        status->error.auth = 1;
 
-               goto out;
+               goto err;
        }
 
        ip = odp_packet_l3_ptr(pkt, NULL);
@@ -921,7 +929,13 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 
        _odp_ipv4_csum_update(pkt);
 
-out:
+       *pkt_out = pkt;
+       return ipsec_sa;
+
+err:
+       pkt_hdr = odp_packet_hdr(pkt);
+
+       pkt_hdr->p.error_flags.ipsec_err = 1;
 
        *pkt_out = pkt;
        return ipsec_sa;

Reply via email to