get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/65445/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 65445,
    "url": "http://patches.dpdk.org/api/patches/65445/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1580492385-120134-7-git-send-email-vladimir.medvedkin@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1580492385-120134-7-git-send-email-vladimir.medvedkin@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1580492385-120134-7-git-send-email-vladimir.medvedkin@intel.com",
    "date": "2020-01-31T17:39:43",
    "name": "[v6,6/8] examples/ipsec-secgw: add SAD cache",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "943f15b8445f54c252cec38d82fce05de6da7fa7",
    "submitter": {
        "id": 1216,
        "url": "http://patches.dpdk.org/api/people/1216/?format=api",
        "name": "Vladimir Medvedkin",
        "email": "vladimir.medvedkin@intel.com"
    },
    "delegate": {
        "id": 6690,
        "url": "http://patches.dpdk.org/api/users/6690/?format=api",
        "username": "akhil",
        "first_name": "akhil",
        "last_name": "goyal",
        "email": "gakhil@marvell.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1580492385-120134-7-git-send-email-vladimir.medvedkin@intel.com/mbox/",
    "series": [
        {
            "id": 8384,
            "url": "http://patches.dpdk.org/api/series/8384/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8384",
            "date": "2020-01-31T17:39:37",
            "name": "integrate librte_ipsec SAD into ipsec-secgw",
            "version": 6,
            "mbox": "http://patches.dpdk.org/series/8384/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/65445/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/65445/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 61FC8A0524;\n\tFri, 31 Jan 2020 18:40:51 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 56C891C199;\n\tFri, 31 Jan 2020 18:40:07 +0100 (CET)",
            "from mga06.intel.com (mga06.intel.com [134.134.136.31])\n by dpdk.org (Postfix) with ESMTP id 2B7341C127\n for <dev@dpdk.org>; Fri, 31 Jan 2020 18:39:58 +0100 (CET)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n 31 Jan 2020 09:39:57 -0800",
            "from silpixa00400072.ir.intel.com ([10.237.222.213])\n by orsmga008.jf.intel.com with ESMTP; 31 Jan 2020 09:39:56 -0800"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.70,386,1574150400\"; d=\"scan'208\";a=\"223202821\"",
        "From": "Vladimir Medvedkin <vladimir.medvedkin@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "konstantin.ananyev@intel.com,\n\takhil.goyal@nxp.com",
        "Date": "Fri, 31 Jan 2020 17:39:43 +0000",
        "Message-Id": "<1580492385-120134-7-git-send-email-vladimir.medvedkin@intel.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": [
            "<1580492385-120134-1-git-send-email-vladimir.medvedkin@intel.com>",
            "<1580306768-110555-1-git-send-email-vladimir.medvedkin@intel.com>"
        ],
        "References": [
            "<1580492385-120134-1-git-send-email-vladimir.medvedkin@intel.com>",
            "<1580306768-110555-1-git-send-email-vladimir.medvedkin@intel.com>"
        ],
        "Subject": "[dpdk-dev] [PATCH v6 6/8] examples/ipsec-secgw: add SAD cache",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Introduce SAD cache.\nStores the most recent SA in a per lcore cache.\nCache represents flat array containing SA's indexed by SPI.\n\nSigned-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>\nAcked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>\nAcked-by: Akhil Goyal <akhil.goyal@nxp.com>\n---\n examples/ipsec-secgw/ipsec-secgw.c |  30 +++++++++-\n examples/ipsec-secgw/ipsec.h       |   1 +\n examples/ipsec-secgw/sa.c          |  32 +----------\n examples/ipsec-secgw/sad.c         |  40 +++++++++++++\n examples/ipsec-secgw/sad.h         | 111 ++++++++++++++++++++++++++++++++++---\n 5 files changed, 173 insertions(+), 41 deletions(-)",
    "diff": "diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c\nindex 3e5f82e..32ecd26 100644\n--- a/examples/ipsec-secgw/ipsec-secgw.c\n+++ b/examples/ipsec-secgw/ipsec-secgw.c\n@@ -46,6 +46,7 @@\n \n #include \"ipsec.h\"\n #include \"parser.h\"\n+#include \"sad.h\"\n \n #define RTE_LOGTYPE_IPSEC RTE_LOGTYPE_USER1\n \n@@ -192,7 +193,10 @@ static uint32_t mtu_size = RTE_ETHER_MTU;\n static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;\n \n /* application wide librte_ipsec/SA parameters */\n-struct app_sa_prm app_sa_prm = {.enable = 0};\n+struct app_sa_prm app_sa_prm = {\n+\t\t\t.enable = 0,\n+\t\t\t.cache_sz = SA_CACHE_SZ\n+\t\t};\n static const char *cfgfile;\n \n struct lcore_rx_queue {\n@@ -1102,7 +1106,7 @@ main_loop(__attribute__((unused)) void *dummy)\n \tuint16_t portid;\n \tuint8_t queueid;\n \tstruct lcore_conf *qconf;\n-\tint32_t socket_id;\n+\tint32_t rc, socket_id;\n \tconst uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)\n \t\t\t/ US_PER_S * BURST_TX_DRAIN_US;\n \tstruct lcore_rx_queue *rxql;\n@@ -1132,6 +1136,14 @@ main_loop(__attribute__((unused)) void *dummy)\n \tqconf->frag.pool_dir = socket_ctx[socket_id].mbuf_pool;\n \tqconf->frag.pool_indir = socket_ctx[socket_id].mbuf_pool_indir;\n \n+\trc = ipsec_sad_lcore_cache_init(app_sa_prm.cache_sz);\n+\tif (rc != 0) {\n+\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\"SAD cache init on lcore %u, failed with code: %d\\n\",\n+\t\t\tlcore_id, rc);\n+\t\treturn rc;\n+\t}\n+\n \tif (qconf->nb_rx_queue == 0) {\n \t\tRTE_LOG(DEBUG, IPSEC, \"lcore %u has nothing to do\\n\",\n \t\t\tlcore_id);\n@@ -1271,6 +1283,7 @@ print_usage(const char *prgname)\n \t\t\" [-w REPLAY_WINDOW_SIZE]\"\n \t\t\" [-e]\"\n \t\t\" [-a]\"\n+\t\t\" [-c]\"\n \t\t\" -f CONFIG_FILE\"\n \t\t\" --config (port,queue,lcore)[,(port,queue,lcore)]\"\n \t\t\" [--single-sa SAIDX]\"\n@@ -1290,6 +1303,8 @@ print_usage(const char *prgname)\n \t\t\"     size for each SA\\n\"\n \t\t\"  -e enables ESN\\n\"\n \t\t\"  -a enables SA SQN atomic behaviour\\n\"\n+\t\t\"  -c specifies inbound SAD cache size,\\n\"\n+\t\t\"     zero value disables the cache (default value: 128)\\n\"\n \t\t\"  -f CONFIG_FILE: Configuration file\\n\"\n \t\t\"  --config (port,queue,lcore): Rx queue configuration\\n\"\n \t\t\"  --single-sa SAIDX: Use single SA index for outbound traffic,\\n\"\n@@ -1442,7 +1457,7 @@ parse_args(int32_t argc, char **argv)\n \n \targvopt = argv;\n \n-\twhile ((opt = getopt_long(argc, argvopt, \"aelp:Pu:f:j:w:\",\n+\twhile ((opt = getopt_long(argc, argvopt, \"aelp:Pu:f:j:w:c:\",\n \t\t\t\tlgopts, &option_index)) != EOF) {\n \n \t\tswitch (opt) {\n@@ -1501,6 +1516,15 @@ parse_args(int32_t argc, char **argv)\n \t\t\tapp_sa_prm.enable = 1;\n \t\t\tapp_sa_prm.flags |= RTE_IPSEC_SAFLAG_SQN_ATOM;\n \t\t\tbreak;\n+\t\tcase 'c':\n+\t\t\tret = parse_decimal(optarg);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tprintf(\"Invalid SA cache size: %s\\n\", optarg);\n+\t\t\t\tprint_usage(prgname);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tapp_sa_prm.cache_sz = ret;\n+\t\t\tbreak;\n \t\tcase CMD_LINE_OPT_CONFIG_NUM:\n \t\t\tret = parse_config(optarg);\n \t\t\tif (ret) {\ndiff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h\nindex 3c77232..4f2fd61 100644\n--- a/examples/ipsec-secgw/ipsec.h\n+++ b/examples/ipsec-secgw/ipsec.h\n@@ -81,6 +81,7 @@ struct app_sa_prm {\n \tuint32_t enable; /* use librte_ipsec API for ipsec pkt processing */\n \tuint32_t window_size; /* replay window size */\n \tuint32_t enable_esn;  /* enable/disable ESN support */\n+\tuint32_t cache_sz;\t/* per lcore SA cache size */\n \tuint64_t flags;       /* rte_ipsec_sa_prm.flags */\n };\n \ndiff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c\nindex b3b83e3..099a11b 100644\n--- a/examples/ipsec-secgw/sa.c\n+++ b/examples/ipsec-secgw/sa.c\n@@ -839,7 +839,7 @@ sa_create(const char *name, int32_t socket_id, uint32_t nb_sa)\n \t\treturn NULL;\n \t}\n \n-\tsa_ctx = rte_malloc(NULL, sizeof(struct sa_ctx) +\n+\tsa_ctx = rte_zmalloc(NULL, sizeof(struct sa_ctx) +\n \t\tsizeof(struct ipsec_sa) * nb_sa, RTE_CACHE_LINE_SIZE);\n \n \tif (sa_ctx == NULL) {\n@@ -1451,9 +1451,6 @@ inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],\n \t\tvoid *sa_arr[], uint16_t nb_pkts)\n {\n \tuint32_t i;\n-\tstruct ip *ip;\n-\tuint32_t *src4_addr;\n-\tuint8_t *src6_addr;\n \tvoid *result_sa;\n \tstruct ipsec_sa *sa;\n \n@@ -1479,32 +1476,7 @@ inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],\n \t\t\tintsa |= IPSEC_SA_OFFLOAD_FALLBACK_FLAG;\n \t\t\tresult_sa = (void *)intsa;\n \t\t}\n-\n-\t\tip = rte_pktmbuf_mtod(pkts[i], struct ip *);\n-\t\tswitch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {\n-\t\tcase IP4_TUNNEL:\n-\t\t\tsrc4_addr = RTE_PTR_ADD(ip,\n-\t\t\t\toffsetof(struct ip, ip_src));\n-\t\t\tif ((ip->ip_v == IPVERSION) &&\n-\t\t\t\t\t(sa->src.ip.ip4 == *src4_addr) &&\n-\t\t\t\t\t(sa->dst.ip.ip4 == *(src4_addr + 1)))\n-\t\t\t\tsa_arr[i] = result_sa;\n-\t\t\telse\n-\t\t\t\tsa_arr[i] = NULL;\n-\t\t\tbreak;\n-\t\tcase IP6_TUNNEL:\n-\t\t\tsrc6_addr = RTE_PTR_ADD(ip,\n-\t\t\t\toffsetof(struct ip6_hdr, ip6_src));\n-\t\t\tif ((ip->ip_v == IP6_VERSION) &&\n-\t\t\t\t!memcmp(&sa->src.ip.ip6.ip6, src6_addr, 16) &&\n-\t\t\t\t!memcmp(&sa->dst.ip.ip6.ip6, src6_addr + 16, 16))\n-\t\t\t\tsa_arr[i] = result_sa;\n-\t\t\telse\n-\t\t\t\tsa_arr[i] = NULL;\n-\t\t\tbreak;\n-\t\tcase TRANSPORT:\n-\t\t\tsa_arr[i] = result_sa;\n-\t\t}\n+\t\tsa_arr[i] = result_sa;\n \t}\n }\n \ndiff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c\nindex fd31101..5b2c0e6 100644\n--- a/examples/ipsec-secgw/sad.c\n+++ b/examples/ipsec-secgw/sad.c\n@@ -3,10 +3,17 @@\n  */\n \n #include <rte_errno.h>\n+#include <rte_malloc.h>\n \n #include \"ipsec.h\"\n #include \"sad.h\"\n \n+RTE_DEFINE_PER_LCORE(struct ipsec_sad_cache, sad_cache) = {\n+\t.v4 = NULL,\n+\t.v6 = NULL,\n+\t.mask = 0,\n+};\n+\n int\n ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)\n {\n@@ -65,6 +72,39 @@ ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)\n \treturn 0;\n }\n \n+/*\n+ * Init per lcore SAD cache.\n+ * Must be called by every processing lcore.\n+ */\n+int\n+ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent)\n+{\n+\tuint32_t cache_elem;\n+\tsize_t cache_mem_sz;\n+\tstruct ipsec_sad_cache *cache;\n+\n+\tcache = &RTE_PER_LCORE(sad_cache);\n+\n+\tcache_elem = rte_align32pow2(nb_cache_ent);\n+\tcache_mem_sz = sizeof(struct ipsec_sa *) * cache_elem;\n+\n+\tif (cache_mem_sz != 0) {\n+\t\tcache->v4 = rte_zmalloc_socket(NULL, cache_mem_sz,\n+\t\t\tRTE_CACHE_LINE_SIZE, rte_socket_id());\n+\t\tif (cache->v4 == NULL)\n+\t\t\treturn -rte_errno;\n+\n+\t\tcache->v6 = rte_zmalloc_socket(NULL, cache_mem_sz,\n+\t\t\tRTE_CACHE_LINE_SIZE, rte_socket_id());\n+\t\tif (cache->v6 == NULL)\n+\t\t\treturn -rte_errno;\n+\n+\t\tcache->mask = cache_elem - 1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n int\n ipsec_sad_create(const char *name, struct ipsec_sad *sad,\n \tint socket_id, struct ipsec_sa_cnt *sa_cnt)\ndiff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h\nindex 29ed0f8..3f92db2 100644\n--- a/examples/ipsec-secgw/sad.h\n+++ b/examples/ipsec-secgw/sad.h\n@@ -7,6 +7,17 @@\n \n #include <rte_ipsec_sad.h>\n \n+#define SA_CACHE_SZ\t128\n+#define SPI2IDX(spi, mask)\t((spi) & (mask))\n+\n+struct ipsec_sad_cache {\n+\tstruct ipsec_sa **v4;\n+\tstruct ipsec_sa **v6;\n+\tuint32_t mask;\n+};\n+\n+RTE_DECLARE_PER_LCORE(struct ipsec_sad_cache, sad_cache);\n+\n struct ipsec_sad {\n \tstruct rte_ipsec_sad *sad_v4;\n \tstruct rte_ipsec_sad *sad_v6;\n@@ -17,8 +28,42 @@ int ipsec_sad_create(const char *name, struct ipsec_sad *sad,\n \n int ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa);\n \n+int ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent);\n+\n+static inline int\n+cmp_sa_key(struct ipsec_sa *sa, int is_v4, struct rte_ipv4_hdr *ipv4,\n+\tstruct rte_ipv6_hdr *ipv6)\n+{\n+\tint sa_type = WITHOUT_TRANSPORT_VERSION(sa->flags);\n+\tif ((sa_type == TRANSPORT) ||\n+\t\t\t/* IPv4 check */\n+\t\t\t(is_v4 && (sa_type == IP4_TUNNEL) &&\n+\t\t\t(sa->src.ip.ip4 == ipv4->src_addr) &&\n+\t\t\t(sa->dst.ip.ip4 == ipv4->dst_addr)) ||\n+\t\t\t/* IPv6 check */\n+\t\t\t(!is_v4 && (sa_type == IP6_TUNNEL) &&\n+\t\t\t(!memcmp(sa->src.ip.ip6.ip6, ipv6->src_addr, 16)) &&\n+\t\t\t(!memcmp(sa->dst.ip.ip6.ip6, ipv6->dst_addr, 16))))\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n static inline void\n-sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],\n+sa_cache_update(struct ipsec_sa **sa_cache, struct ipsec_sa *sa, uint32_t mask)\n+{\n+\tuint32_t cache_idx;\n+\n+\t/* SAD cache is disabled */\n+\tif (mask == 0)\n+\t\treturn;\n+\n+\tcache_idx = SPI2IDX(sa->spi, mask);\n+\tsa_cache[cache_idx] = sa;\n+}\n+\n+static inline void\n+sad_lookup(struct ipsec_sad *sad, struct rte_mbuf *pkts[],\n \tvoid *sa[], uint16_t nb_pkts)\n {\n \tuint32_t i;\n@@ -34,13 +79,39 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],\n \tconst union rte_ipsec_sad_key\t*keys_v6[nb_pkts];\n \tvoid *v4_res[nb_pkts];\n \tvoid *v6_res[nb_pkts];\n+\tuint32_t spi, cache_idx;\n+\tstruct ipsec_sad_cache *cache;\n+\tstruct ipsec_sa *cached_sa;\n+\tint is_ipv4;\n+\n+\tcache  = &RTE_PER_LCORE(sad_cache);\n \n \t/* split received packets by address family into two arrays */\n \tfor (i = 0; i < nb_pkts; i++) {\n \t\tipv4 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv4_hdr *);\n+\t\tipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *);\n \t\tesp = rte_pktmbuf_mtod_offset(pkts[i], struct rte_esp_hdr *,\n \t\t\t\tpkts[i]->l3_len);\n-\t\tif ((ipv4->version_ihl >> 4) == IPVERSION) {\n+\n+\t\tis_ipv4 = ((ipv4->version_ihl >> 4) == IPVERSION);\n+\t\tspi = rte_be_to_cpu_32(esp->spi);\n+\t\tcache_idx = SPI2IDX(spi, cache->mask);\n+\n+\t\tif (is_ipv4) {\n+\t\t\tcached_sa = (cache->mask != 0) ?\n+\t\t\t\tcache->v4[cache_idx] : NULL;\n+\t\t\t/* check SAD cache entry */\n+\t\t\tif ((cached_sa != NULL) && (cached_sa->spi == spi)) {\n+\t\t\t\tif (cmp_sa_key(cached_sa, 1, ipv4, ipv6)) {\n+\t\t\t\t\t/* cache hit */\n+\t\t\t\t\tsa[i] = cached_sa;\n+\t\t\t\t\tcontinue;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t/*\n+\t\t\t * cache miss\n+\t\t\t * preparing sad key to proceed with sad lookup\n+\t\t\t */\n \t\t\tv4[nb_v4].spi = esp->spi;\n \t\t\tv4[nb_v4].dip = ipv4->dst_addr;\n \t\t\tv4[nb_v4].sip = ipv4->src_addr;\n@@ -48,7 +119,14 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],\n \t\t\t\t\t\t&v4[nb_v4];\n \t\t\tv4_idxes[nb_v4++] = i;\n \t\t} else {\n-\t\t\tipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *);\n+\t\t\tcached_sa = (cache->mask != 0) ?\n+\t\t\t\tcache->v6[cache_idx] : NULL;\n+\t\t\tif ((cached_sa != NULL) && (cached_sa->spi == spi)) {\n+\t\t\t\tif (cmp_sa_key(cached_sa, 0, ipv4, ipv6)) {\n+\t\t\t\t\tsa[i] = cached_sa;\n+\t\t\t\t\tcontinue;\n+\t\t\t\t}\n+\t\t\t}\n \t\t\tv6[nb_v6].spi = esp->spi;\n \t\t\tmemcpy(v6[nb_v6].dip, ipv6->dst_addr,\n \t\t\t\t\tsizeof(ipv6->dst_addr));\n@@ -65,11 +143,28 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],\n \tif (nb_v6 != 0)\n \t\trte_ipsec_sad_lookup(sad->sad_v6, keys_v6, v6_res, nb_v6);\n \n-\tfor (i = 0; i < nb_v4; i++)\n-\t\tsa[v4_idxes[i]] = v4_res[i];\n-\n-\tfor (i = 0; i < nb_v6; i++)\n-\t\tsa[v6_idxes[i]] = v6_res[i];\n+\tfor (i = 0; i < nb_v4; i++) {\n+\t\tipv4 = rte_pktmbuf_mtod(pkts[v4_idxes[i]],\n+\t\t\tstruct rte_ipv4_hdr *);\n+\t\tif ((v4_res[i] != NULL) &&\n+\t\t\t\t(cmp_sa_key(v4_res[i], 1, ipv4, NULL))) {\n+\t\t\tsa[v4_idxes[i]] = v4_res[i];\n+\t\t\tsa_cache_update(cache->v4, (struct ipsec_sa *)v4_res[i],\n+\t\t\t\tcache->mask);\n+\t\t} else\n+\t\t\tsa[v4_idxes[i]] = NULL;\n+\t}\n+\tfor (i = 0; i < nb_v6; i++) {\n+\t\tipv6 = rte_pktmbuf_mtod(pkts[v6_idxes[i]],\n+\t\t\tstruct rte_ipv6_hdr *);\n+\t\tif ((v6_res[i] != NULL) &&\n+\t\t\t\t(cmp_sa_key(v6_res[i], 0, NULL, ipv6))) {\n+\t\t\tsa[v6_idxes[i]] = v6_res[i];\n+\t\t\tsa_cache_update(cache->v6, (struct ipsec_sa *)v6_res[i],\n+\t\t\t\tcache->mask);\n+\t\t} else\n+\t\t\tsa[v6_idxes[i]] = NULL;\n+\t}\n }\n \n #endif /* __SAD_H__ */\n",
    "prefixes": [
        "v6",
        "6/8"
    ]
}