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

Support checking MTU after IPsec transformation.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsoleni...@linaro.org>
---
/** Email created from pull request 304 (lumag:ipsec-ipv6-2)
 ** https://github.com/Linaro/odp/pull/304
 ** Patch: https://github.com/Linaro/odp/pull/304.patch
 ** Base sha: 4cb02e1caccb9179575e95448fd46979e17d0905
 ** Merge commit sha: 6f6906b608f0626d119b255b3733a4a0863aa8d1
 **/
 platform/linux-generic/odp_ipsec.c | 39 ++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/platform/linux-generic/odp_ipsec.c 
b/platform/linux-generic/odp_ipsec.c
index 3c539b515..a393c5051 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -990,7 +990,8 @@ static int ipsec_out_esp(odp_packet_t *pkt,
                         ipsec_state_t *state,
                         ipsec_sa_t *ipsec_sa,
                         odp_crypto_packet_op_param_t *param,
-                        odp_ipsec_op_status_t *status)
+                        odp_ipsec_op_status_t *status,
+                        uint32_t mtu)
 {
        _odp_esphdr_t esp;
        _odp_esptrl_t esptrl;
@@ -1026,6 +1027,11 @@ static int ipsec_out_esp(odp_packet_t *pkt,
                udphdr.chksum = 0; /* should be 0 by RFC */
        }
 
+       if (state->ip_tot_len + hdr_len + trl_len > mtu) {
+               status->error.mtu = 1;
+               return -1;
+       }
+
        if (ipsec_out_iv(state, ipsec_sa) < 0) {
                status->error.alg = 1;
                return -1;
@@ -1124,7 +1130,8 @@ static int ipsec_out_ah(odp_packet_t *pkt,
                        ipsec_state_t *state,
                        ipsec_sa_t *ipsec_sa,
                        odp_crypto_packet_op_param_t *param,
-                       odp_ipsec_op_status_t *status)
+                       odp_ipsec_op_status_t *status,
+                       uint32_t mtu)
 {
        _odp_ahhdr_t ah;
        unsigned hdr_len = _ODP_AHHDR_LEN + ipsec_sa->esp_iv_len +
@@ -1132,6 +1139,11 @@ static int ipsec_out_ah(odp_packet_t *pkt,
        uint16_t ipsec_offset = state->ip_offset + state->ip_hdr_len;
        uint8_t proto = _ODP_IPPROTO_AH;
 
+       if (state->ip_tot_len + hdr_len > mtu) {
+               status->error.mtu = 1;
+               return -1;
+       }
+
        memset(&ah, 0, sizeof(ah));
        ah.spi = odp_cpu_to_be_32(ipsec_sa->spi);
        ah.seq_no = odp_cpu_to_be_32(ipsec_seq_no(ipsec_sa));
@@ -1228,7 +1240,7 @@ static void ipsec_out_ah_post(ipsec_state_t *state, 
odp_packet_t pkt)
 static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
                                    odp_ipsec_sa_t sa,
                                    odp_packet_t *pkt_out,
-                                   const odp_ipsec_out_opt_t *opt ODP_UNUSED,
+                                   const odp_ipsec_out_opt_t *opt,
                                    odp_ipsec_op_status_t *status)
 {
        ipsec_state_t state;
@@ -1237,6 +1249,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
        int rc;
        odp_crypto_packet_result_t crypto; /**< Crypto operation result */
        odp_packet_hdr_t *pkt_hdr;
+       uint32_t mtu;
 
        state.ip_offset = odp_packet_l3_offset(pkt);
        ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != state.ip_offset);
@@ -1247,6 +1260,12 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
        ipsec_sa = _odp_ipsec_sa_use(sa);
        ODP_ASSERT(NULL != ipsec_sa);
 
+       if ((opt && opt->mode == ODP_IPSEC_FRAG_CHECK) ||
+           (!opt && ipsec_sa->out.frag_mode == ODP_IPSEC_FRAG_CHECK))
+               mtu = ipsec_sa->out.mtu;
+       else
+               mtu = UINT32_MAX;
+
        /* Initialize parameters block */
        memset(&param, 0, sizeof(param));
 
@@ -1281,9 +1300,9 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
        }
 
        if (ODP_IPSEC_ESP == ipsec_sa->proto) {
-               rc = ipsec_out_esp(&pkt, &state, ipsec_sa, &param, status);
+               rc = ipsec_out_esp(&pkt, &state, ipsec_sa, &param, status, mtu);
        } else if (ODP_IPSEC_AH == ipsec_sa->proto) {
-               rc = ipsec_out_ah(&pkt, &state, ipsec_sa, &param, status);
+               rc = ipsec_out_ah(&pkt, &state, ipsec_sa, &param, status, mtu);
        } else {
                status->error.alg = 1;
                goto err;
@@ -1402,10 +1421,6 @@ int odp_ipsec_in(const odp_packet_t pkt_in[], int num_in,
        return in_pkt;
 }
 
-static const odp_ipsec_out_opt_t default_opt = {
-       .mode = ODP_IPSEC_FRAG_DISABLED,
-};
-
 int odp_ipsec_out(const odp_packet_t pkt_in[], int num_in,
                  odp_packet_t pkt_out[], int *num_out,
                  const odp_ipsec_out_param_t *param)
@@ -1434,7 +1449,7 @@ int odp_ipsec_out(const odp_packet_t pkt_in[], int num_in,
                ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa);
 
                if (0 == param->num_opt)
-                       opt = &default_opt;
+                       opt = NULL;
                else
                        opt = &param->opt[opt_idx];
 
@@ -1543,7 +1558,7 @@ int odp_ipsec_out_enq(const odp_packet_t pkt_in[], int 
num_in,
                ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa);
 
                if (0 == param->num_opt)
-                       opt = &default_opt;
+                       opt = NULL;
                else
                        opt = &param->opt[opt_idx];
 
@@ -1640,7 +1655,7 @@ int odp_ipsec_out_inline(const odp_packet_t pkt_in[], int 
num_in,
                }
 
                if (0 == param->num_opt)
-                       opt = &default_opt;
+                       opt = NULL;
                else
                        opt = &param->opt[opt_idx];
 

Reply via email to