JannePeltonen replied on github web page:

platform/linux-generic/odp_ipsec.c
line 604
@@ -4,179 +4,1244 @@
  * SPDX-License-Identifier:     BSD-3-Clause
  */
 
+#include "config.h"
+
 #include <odp/api/ipsec.h>
 
+#include <odp_debug_internal.h>
+#include <odp_packet_internal.h>
+#include <odp_ipsec_internal.h>
+
+#include <protocols/eth.h>
+#include <protocols/ip.h>
+#include <protocols/ipsec.h>
+
 #include <string.h>
 
+typedef struct ODP_PACKED {
+       odp_u32be_t spi;     /**< Security Parameter Index */
+       odp_u32be_t seq_no;  /**< Sequence Number */
+} ipsec_aad_t;
+
 int odp_ipsec_capability(odp_ipsec_capability_t *capa)
 {
+       int rc;
+       odp_crypto_capability_t crypto_capa;
+       odp_queue_capability_t queue_capa;
+
        memset(capa, 0, sizeof(odp_ipsec_capability_t));
 
+       capa->op_mode_sync = ODP_SUPPORT_PREFERRED;
+       capa->op_mode_async = ODP_SUPPORT_PREFERRED;
+       capa->op_mode_inline_in = ODP_SUPPORT_PREFERRED;
+       capa->op_mode_inline_out = ODP_SUPPORT_PREFERRED;
+
+       capa->proto_ah = ODP_SUPPORT_YES;
+
+       capa->max_num_sa = ODP_CONFIG_IPSEC_SAS;
+
+       rc = odp_crypto_capability(&crypto_capa);
+       if (rc < 0)
+               return rc;
+
+       capa->ciphers = crypto_capa.ciphers;
+       capa->auths = crypto_capa.auths;
+
+       rc = odp_queue_capability(&queue_capa);
+       if (rc < 0)
+               return rc;
+
+       capa->max_queues = queue_capa.max_queues;
+
        return 0;
 }
 
 int odp_ipsec_cipher_capability(odp_cipher_alg_t cipher,
                                odp_crypto_cipher_capability_t capa[], int num)
 {
-       (void)cipher;
-       (void)capa;
-       (void)num;
-
-       return -1;
+       return odp_crypto_cipher_capability(cipher, capa, num);
 }
 
 int odp_ipsec_auth_capability(odp_auth_alg_t auth,
                              odp_crypto_auth_capability_t capa[], int num)
 {
-       (void)auth;
-       (void)capa;
-       (void)num;
-
-       return -1;
+       return odp_crypto_auth_capability(auth, capa, num);
 }
 
 void odp_ipsec_config_init(odp_ipsec_config_t *config)
 {
        memset(config, 0, sizeof(odp_ipsec_config_t));
+       config->inbound_mode = ODP_IPSEC_OP_MODE_SYNC;
+       config->outbound_mode = ODP_IPSEC_OP_MODE_SYNC;
+       config->max_num_sa = ODP_CONFIG_IPSEC_SAS;
+       config->inbound.default_queue = ODP_QUEUE_INVALID;
+       config->inbound.lookup.min_spi = 0;
+       config->inbound.lookup.max_spi = UINT32_MAX;
 }
 
+static odp_ipsec_config_t ipsec_config;
+
 int odp_ipsec_config(const odp_ipsec_config_t *config)
 {
-       (void)config;
+       if (ODP_CONFIG_IPSEC_SAS > config->max_num_sa)
+               return -1;
+
+       ipsec_config = *config;
+
+       return 0;
+}
+
+static odp_ipsec_packet_result_t *ipsec_pkt_result(odp_packet_t packet)
+{
+       ODP_ASSERT(ODP_EVENT_PACKET_IPSEC ==
+                  odp_event_subtype(odp_packet_to_event(packet)));
+
+       return &odp_packet_hdr(packet)->ipsec_ctx;
+}
+
+/**
+ * Checksum
+ *
+ * @param buffer calculate chksum for buffer
+ * @param len    buffer length
+ *
+ * @return checksum value in network order
+ */
+static inline
+odp_u16sum_t _odp_chksum(void *buffer, int len)
+{
+       uint16_t *buf = (uint16_t *)buffer;
+       uint32_t sum = 0;
+       uint16_t result;
+
+       for (sum = 0; len > 1; len -= 2)
+               sum += *buf++;
 
-       return -1;
+       if (len == 1)
+               sum += *(unsigned char *)buf;
+
+       sum = (sum >> 16) + (sum & 0xFFFF);
+       sum += (sum >> 16);
+       result = ~sum;
+
+       return  (__odp_force odp_u16sum_t) result;
 }
 
-void odp_ipsec_sa_param_init(odp_ipsec_sa_param_t *param)
+static inline int _odp_ipv4_csum(odp_packet_t pkt,
+                                uint32_t offset,
+                                _odp_ipv4hdr_t *ip,
+                                odp_u16sum_t *chksum)
 {
-       memset(param, 0, sizeof(odp_ipsec_sa_param_t));
+       unsigned nleft = _ODP_IPV4HDR_IHL(ip->ver_ihl) * 4;
+       uint16_t buf[nleft / 2];
+       int res;
+
+       if (odp_unlikely(nleft < sizeof(*ip)))
+               return -1;
+       ip->chksum = 0;
+       memcpy(buf, ip, sizeof(*ip));
+       res = odp_packet_copy_to_mem(pkt, offset + sizeof(*ip),
+                                    nleft - sizeof(*ip),
+                                    buf + sizeof(*ip) / 2);
+       if (odp_unlikely(res < 0))
+               return res;
+
+       *chksum = _odp_chksum(buf, nleft);
+
+       return 0;
 }
 
-odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param)
+/** @internal Checksum offset in IPv4 header */
+#define _ODP_IPV4HDR_CSUM_OFFSET       10
+
+/**
+ * Calculate and fill in IPv4 checksum
+ *
+ * @param pkt  ODP packet
+ *
+ * @retval 0 on success
+ * @retval <0 on failure
+ */
+static inline int _odp_ipv4_csum_update(odp_packet_t pkt)
 {
-       (void)param;
+       uint32_t offset;
+       _odp_ipv4hdr_t ip;
+       odp_u16sum_t chksum;
+       int res;
+
+       offset = odp_packet_l3_offset(pkt);
+       if (offset == ODP_PACKET_OFFSET_INVALID)
+               return -1;
+
+       res = odp_packet_copy_to_mem(pkt, offset, sizeof(ip), &ip);
+       if (odp_unlikely(res < 0))
+               return res;
 
-       return ODP_IPSEC_SA_INVALID;
+       res = _odp_ipv4_csum(pkt, offset, &ip, &chksum);
+       if (odp_unlikely(res < 0))
+               return res;
+
+       return odp_packet_copy_from_mem(pkt,
+                                       offset + _ODP_IPV4HDR_CSUM_OFFSET,
+                                       2, &chksum);
 }
 
-int odp_ipsec_sa_disable(odp_ipsec_sa_t sa)
+#define ipv4_hdr_len(ip) (_ODP_IPV4HDR_IHL(ip->ver_ihl) * 4)
+static inline
+void ipv4_adjust_len(_odp_ipv4hdr_t *ip, int adj)
 {
-       (void)sa;
+       ip->tot_len = odp_cpu_to_be_16(odp_be_to_cpu_16(ip->tot_len) + adj);
+}
+
+static const uint8_t ipsec_padding[255] = {
+             0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+};
+
+static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
+                                  odp_ipsec_sa_t sa,
+                                  odp_packet_t *pkt_out,
+                                  odp_ipsec_op_status_t *status)
+{
+       ipsec_sa_t *ipsec_sa = NULL;
+       uint32_t ip_offset = odp_packet_l3_offset(pkt);
+       _odp_ipv4hdr_t *ip = odp_packet_l3_ptr(pkt, NULL);
+       uint16_t ip_hdr_len = ipv4_hdr_len(ip);
+       odp_crypto_packet_op_param_t param;
+       int rc;
+       unsigned stats_length;
+       uint16_t ipsec_offset;   /**< Offset of IPsec header from
+                                     buffer start */
+       uint8_t iv[MAX_IV_LEN];  /**< ESP IV storage */
+       ipsec_aad_t aad;         /**< AAD, note ESN is not fully supported */
+       unsigned hdr_len;        /**< Length of IPsec headers */
+       unsigned trl_len;        /**< Length of IPsec trailers */
+       uint8_t  ip_tos;         /**< Saved IP TOS value */
+       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_ASSERT(ODP_PACKET_OFFSET_INVALID != ip_offset);
+       ODP_ASSERT(NULL != ip);
+
+       ip_tos = 0;
+       ip_ttl = 0;
+       ip_frag_offset = 0;
+
+       /* Initialize parameters block */
+       memset(&param, 0, sizeof(param));
+
+       ipsec_offset = ip_offset + ip_hdr_len;
+
+       if (_ODP_IPV4HDR_IS_FRAGMENT(ip->frag_offset)) {
+               status->error.proto = 1;
+               goto out;
+       }
+
+       /* Check IP header for IPSec protocols and look it up */
+       if (_ODP_IPPROTO_ESP == ip->proto) {
+               _odp_esphdr_t esp;
+
+               if (odp_packet_copy_to_mem(pkt, ipsec_offset,
+                                          sizeof(esp), &esp) < 0) {
+                       status->error.alg = 1;
+                       goto out;
+               }
+
+               if (ODP_IPSEC_SA_INVALID == sa) {
+                       ipsec_sa_lookup_t lookup;
+
+                       lookup.proto = ODP_IPSEC_ESP;
+                       lookup.spi = odp_be_to_cpu_32(esp.spi);
+                       lookup.dst_addr = &ip->dst_addr;
+
+                       ipsec_sa = _odp_ipsec_sa_lookup(&lookup);
+                       if (NULL == ipsec_sa) {
+                               status->error.sa_lookup = 1;
+                               goto out;
+                       }
+               } else {
+                       ipsec_sa = _odp_ipsec_sa_use(sa);
+                       ODP_ASSERT(NULL != ipsec_sa);
+                       if (ipsec_sa->proto != ODP_IPSEC_ESP ||
+                           ipsec_sa->spi != odp_be_to_cpu_32(esp.spi)) {
+                               status->error.proto = 1;
+                               goto out;
+                       }
+               }
+
+               memcpy(iv, ipsec_sa->salt, ipsec_sa->salt_length);
+               if (odp_packet_copy_to_mem(pkt,
+                                          ipsec_offset + _ODP_ESPHDR_LEN,
+                                          ipsec_sa->esp_iv_len,
+                                          iv + ipsec_sa->salt_length) < 0) {
+                       status->error.alg = 1;
+                       goto out;
+               }
+
+               hdr_len = _ODP_ESPHDR_LEN + ipsec_sa->esp_iv_len;
+               trl_len = _ODP_ESPTRL_LEN + ipsec_sa->icv_len;
 
-       return -1;
+               param.cipher_range.offset = ipsec_offset + hdr_len;
+               param.cipher_range.length = odp_be_to_cpu_16(ip->tot_len) -
+                                           ip_hdr_len -
+                                           hdr_len -
+                                           ipsec_sa->icv_len;
+               param.override_iv_ptr = iv;
+
+               aad.spi = esp.spi;
+               aad.seq_no = esp.seq_no;
+
+               param.aad.ptr = (uint8_t *)&aad;
+               param.aad.length = sizeof(aad);
+
+               param.auth_range.offset = ipsec_offset;
+               param.auth_range.length = odp_be_to_cpu_16(ip->tot_len) -
+                                         ip_hdr_len -
+                                         ipsec_sa->icv_len;
+               param.hash_result_offset = ip_offset +
+                                          odp_be_to_cpu_16(ip->tot_len) -
+                                          ipsec_sa->icv_len;
+
+               stats_length = param.cipher_range.length;
+       } else if (_ODP_IPPROTO_AH == ip->proto) {
+               _odp_ahhdr_t ah;
+
+               if (odp_packet_copy_to_mem(pkt, ipsec_offset,
+                                          sizeof(ah), &ah) < 0) {
+                       status->error.alg = 1;
+                       goto out;
+               }
+
+               if (ODP_IPSEC_SA_INVALID == sa) {
+                       ipsec_sa_lookup_t lookup;
+
+                       lookup.proto = ODP_IPSEC_AH;
+                       lookup.spi = odp_be_to_cpu_32(ah.spi);
+                       lookup.dst_addr = &ip->dst_addr;
+
+                       ipsec_sa = _odp_ipsec_sa_lookup(&lookup);
+                       if (NULL == ipsec_sa) {
+                               status->error.sa_lookup = 1;
+                               goto out;
+                       }
+               } else {
+                       ipsec_sa = _odp_ipsec_sa_use(sa);
+                       ODP_ASSERT(NULL != ipsec_sa);
+                       if (ipsec_sa->proto != ODP_IPSEC_AH ||
+                           ipsec_sa->spi != odp_be_to_cpu_32(ah.spi)) {
+                               status->error.proto = 1;
+                               goto out;
+                       }
+               }
+
+               hdr_len = (ah.ah_len + 2) * 4;
+               trl_len = 0;
+
+               /* Save everything to context */
+               ip_tos = ip->tos;
+               ip_frag_offset = odp_be_to_cpu_16(ip->frag_offset);
+               ip_ttl = ip->ttl;
+
+               /* FIXME: zero copy of header, passing it to crypto! */
+               /*
+                * If authenticating, zero the mutable fields build the request
+                */
+               ip->chksum = 0;
+               ip->tos = 0;
+               ip->frag_offset = 0;
+               ip->ttl = 0;
+
+               param.auth_range.offset = ip_offset;
+               param.auth_range.length = odp_be_to_cpu_16(ip->tot_len);
+               param.hash_result_offset = ipsec_offset + _ODP_AHHDR_LEN;
+
+               stats_length = param.auth_range.length;
+       } else {
+               status->error.proto = 1;
+               goto out;
+       }
+
+       if (_odp_ipsec_sa_update_stats(ipsec_sa,
+                                      stats_length,
+                                      status) < 0)
+               goto out;
+
+       param.session = ipsec_sa->session;
+
+       rc = odp_crypto_op(&pkt, &pkt, &param, 1);
+       if (rc < 0) {
+               ODP_DBG("Crypto failed\n");
+               status->error.alg = 1;
+               goto out;
+       }
+
+       rc = odp_crypto_result(&crypto, pkt);
+       if (rc < 0) {
+               ODP_DBG("Crypto failed\n");
+               status->error.alg = 1;
+               goto out;
+       }
+
+       if (!crypto.ok) {
+               if ((crypto.cipher_status.alg_err !=
+                    ODP_CRYPTO_ALG_ERR_NONE) ||
+                   (crypto.cipher_status.hw_err !=
+                    ODP_CRYPTO_HW_ERR_NONE))
+                       status->error.alg = 1;
+
+               if ((crypto.auth_status.alg_err !=
+                    ODP_CRYPTO_ALG_ERR_NONE) ||
+                   (crypto.auth_status.hw_err !=
+                    ODP_CRYPTO_HW_ERR_NONE))
+                       status->error.auth = 1;
+
+               goto out;
+       }
+
+       ip_offset = odp_packet_l3_offset(pkt);
+       ip = odp_packet_l3_ptr(pkt, NULL);
+       ip_hdr_len = ipv4_hdr_len(ip);
+
+       if (_ODP_IPPROTO_ESP == ip->proto) {
+               /*
+                * Finish cipher by finding ESP trailer and processing
+                */
+               _odp_esptrl_t esptrl;
+               uint32_t esptrl_offset = ip_offset +
+                                        odp_be_to_cpu_16(ip->tot_len) -
+                                        trl_len;
+
+               if (odp_packet_copy_to_mem(pkt, esptrl_offset,
+                                          sizeof(esptrl), &esptrl) < 0) {
+                       status->error.proto = 1;
+                       goto out;
+               }
+
+               if (ip_offset + esptrl.pad_len > esptrl_offset) {
+                       status->error.proto = 1;
+                       goto out;
+               }
+
+               if (_odp_packet_cmp_data(pkt, esptrl_offset - esptrl.pad_len,
+                                        ipsec_padding, esptrl.pad_len) != 0) {
+                       status->error.proto = 1;
+                       goto out;
+               }
+
+               ip->proto = esptrl.next_header;
+               trl_len += esptrl.pad_len;
+       } else if (_ODP_IPPROTO_AH == ip->proto) {
+               /*
+                * Finish auth
+                */
+               _odp_ahhdr_t ah;
+
+               if (odp_packet_copy_to_mem(pkt, ipsec_offset,
+                                          sizeof(ah), &ah) < 0) {
+                       status->error.alg = 1;
+                       goto out;
+               }
+
+               ip->proto = ah.next_header;
+
+               /* Restore mutable fields */
+               ip->ttl = ip_ttl;
+               ip->tos = ip_tos;
+               ip->frag_offset = odp_cpu_to_be_16(ip_frag_offset);
+       } else {
+               status->error.proto = 1;
+               goto out;
+       }
+
+       if (odp_packet_trunc_tail(&pkt, trl_len, NULL, NULL) < 0) {
+               status->error.alg = 1;
+               goto out;
+       }
+
+       if (ODP_IPSEC_MODE_TUNNEL == ipsec_sa->mode) {
+               /* We have a tunneled IPv4 packet, strip outer and IPsec
+                * headers */
+               odp_packet_move_data(pkt, ip_hdr_len + hdr_len, 0,
+                                    ip_offset);
+               if (odp_packet_trunc_head(&pkt, ip_hdr_len + hdr_len,
+                                         NULL, NULL) < 0) {
+                       status->error.alg = 1;
+                       goto out;
+               }
+       } else {
+               odp_packet_move_data(pkt, hdr_len, 0,
+                                    ip_offset + ip_hdr_len);
+               if (odp_packet_trunc_head(&pkt, hdr_len,
+                                         NULL, NULL) < 0) {
+                       status->error.alg = 1;
+                       goto out;
+               }
+       }
+
+       /* Finalize the IPv4 header */
+       if (odp_packet_len(pkt) > sizeof(*ip)) {
+               ip = odp_packet_l3_ptr(pkt, NULL);
+
+               if (ODP_IPSEC_MODE_TRANSPORT == ipsec_sa->mode)
+                       ipv4_adjust_len(ip, -(hdr_len + trl_len));
+
+               ip->ttl -= ipsec_sa->dec_ttl;
+               _odp_ipv4_csum_update(pkt);
+       }
+
+       if (!status->error.all) {
+               odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+               packet_parse_reset(pkt_hdr);
+               /* FIXME: select parsing layer basing on config? */
+               packet_parse_l3_l4(pkt_hdr, ODP_PKTIO_PARSER_LAYER_ALL,
+                                  ip_offset, _ODP_ETHTYPE_IPV4);
+       }
+out:
+       *pkt_out = pkt;
+
+       return ipsec_sa;
 }
 
-int odp_ipsec_sa_destroy(odp_ipsec_sa_t sa)
+/* Generate sequence number */
+static inline
+uint32_t ipsec_seq_no(ipsec_sa_t *ipsec_sa)
 {
-       (void)sa;
+       return odp_atomic_fetch_add_u32(&ipsec_sa->out.seq, 1);
+}
+
+/* Helper for calculating encode length using data length and block size */
+#define ESP_ENCODE_LEN(x, b) ((((x) + ((b) - 1)) / (b)) * (b))
+
+static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
+                                   odp_ipsec_sa_t sa,
+                                   odp_packet_t *pkt_out,
+                                   odp_ipsec_out_opt_t *opt ODP_UNUSED,
+                                   odp_ipsec_op_status_t *status)
+{
+       ipsec_sa_t *ipsec_sa = NULL;
+       uint32_t ip_offset = odp_packet_l3_offset(pkt);
+       _odp_ipv4hdr_t *ip = odp_packet_l3_ptr(pkt, NULL);
+       uint16_t ip_hdr_len = ipv4_hdr_len(ip);
+       odp_crypto_packet_op_param_t param;
+       unsigned stats_length;
+       int rc;
+       uint16_t ipsec_offset;   /**< Offset of IPsec header from
+                                     buffer start */
+       uint8_t iv[MAX_IV_LEN];  /**< ESP IV storage */
+       ipsec_aad_t aad;         /**< AAD, note ESN is not fully supported */
+       unsigned hdr_len;        /**< Length of IPsec headers */
+       unsigned trl_len;        /**< Length of IPsec trailers */
+       uint8_t  ip_tos;         /**< Saved IP TOS value */
+       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_ASSERT(ODP_PACKET_OFFSET_INVALID != ip_offset);
+       ODP_ASSERT(NULL != ip);
+
+       ip_tos = 0;
+       ip_ttl = 0;
+       ip_frag_offset = 0;
+
+       ipsec_sa = _odp_ipsec_sa_use(sa);
+       ODP_ASSERT(NULL != ipsec_sa);
+
+       /* Initialize parameters block */
+       memset(&param, 0, sizeof(param));
+
+       if (ODP_IPSEC_MODE_TRANSPORT == ipsec_sa->mode &&
+           _ODP_IPV4HDR_IS_FRAGMENT(ip->frag_offset)) {


Comment:
_ODP_IPV4HDR_IS_FRAGMENT() expects the parameter word in host byte order. The 
conversion is missing here.

https://github.com/Linaro/odp/pull/81#discussion_r139360242
updated_at 2017-09-18 08:22:39

Reply via email to