get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 28721,
    "url": "https://patches.dpdk.org/api/patches/28721/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20170914082651.26232-12-akhil.goyal@nxp.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<20170914082651.26232-12-akhil.goyal@nxp.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20170914082651.26232-12-akhil.goyal@nxp.com",
    "date": "2017-09-14T08:26:51",
    "name": "[dpdk-dev,11/11] examples/ipsec-secgw: add support for security offload",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "40555355492e3b95a32d7b95ceff6618b6bb7e2a",
    "submitter": {
        "id": 517,
        "url": "https://patches.dpdk.org/api/people/517/?format=api",
        "name": "Akhil Goyal",
        "email": "akhil.goyal@nxp.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20170914082651.26232-12-akhil.goyal@nxp.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/28721/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/28721/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 8CC121B1F8;\n\tThu, 14 Sep 2017 10:29:56 +0200 (CEST)",
            "from NAM01-BN3-obe.outbound.protection.outlook.com\n\t(mail-bn3nam01on0050.outbound.protection.outlook.com [104.47.33.50])\n\tby dpdk.org (Postfix) with ESMTP id 2B4E61B1F7\n\tfor <dev@dpdk.org>; Thu, 14 Sep 2017 10:29:54 +0200 (CEST)",
            "from BLUPR0301CA0036.namprd03.prod.outlook.com (10.162.113.174) by\n\tCY1PR03MB2363.namprd03.prod.outlook.com (10.166.207.150) with\n\tMicrosoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id\n\t15.20.35.12; Thu, 14 Sep 2017 08:29:53 +0000",
            "from BL2FFO11FD008.protection.gbl (2a01:111:f400:7c09::105) by\n\tBLUPR0301CA0036.outlook.office365.com (2a01:111:e400:5259::46) with\n\tMicrosoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.56.11 via\n\tFrontend Transport; Thu, 14 Sep 2017 08:29:52 +0000",
            "from tx30smr01.am.freescale.net (192.88.168.50) by\n\tBL2FFO11FD008.mail.protection.outlook.com (10.173.161.4) with\n\tMicrosoft SMTP Server (version=TLS1_0,\n\tcipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.13.11\n\tvia Frontend Transport; Thu, 14 Sep 2017 08:29:52 +0000",
            "from netperf2.ap.freescale.net ([10.232.133.164])\n\tby tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id\n\tv8E8T36P025953; Thu, 14 Sep 2017 01:29:48 -0700"
        ],
        "Authentication-Results": "spf=fail (sender IP is 192.88.168.50)\n\tsmtp.mailfrom=nxp.com; NXP1.onmicrosoft.com;\n\tdkim=none (message not signed)\n\theader.d=none;NXP1.onmicrosoft.com; dmarc=fail action=none\n\theader.from=nxp.com;",
        "Received-SPF": "Fail (protection.outlook.com: domain of nxp.com does not\n\tdesignate 192.88.168.50 as permitted sender)\n\treceiver=protection.outlook.com; \n\tclient-ip=192.88.168.50; helo=tx30smr01.am.freescale.net;",
        "From": "Akhil Goyal <akhil.goyal@nxp.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<declan.doherty@intel.com>, <pablo.de.lara.guarch@intel.com>,\n\t<hemant.agrawal@nxp.com>, <radu.nicolau@intel.com>,\n\t<borisp@mellanox.com>, \n\t<aviadye@mellanox.com>, <thomas@monjalon.net>, <sandeep.malik@nxp.com>,\n\t<jerin.jacob@caviumnetworks.com>",
        "Date": "Thu, 14 Sep 2017 13:56:51 +0530",
        "Message-ID": "<20170914082651.26232-12-akhil.goyal@nxp.com>",
        "X-Mailer": "git-send-email 2.9.3",
        "In-Reply-To": "<20170914082651.26232-1-akhil.goyal@nxp.com>",
        "References": "<20170914082651.26232-1-akhil.goyal@nxp.com>",
        "X-EOPAttributedMessage": "0",
        "X-Matching-Connectors": "131498513930128762;\n\t(91ab9b29-cfa4-454e-5278-08d120cd25b8); ()",
        "X-Forefront-Antispam-Report": "CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI;\n\tSFV:NSPM;\n\tSFS:(10009020)(6009001)(336005)(39860400002)(39380400002)(376002)(346002)(2980300002)(1109001)(1110001)(339900001)(199003)(189002)(316002)(53946003)(105606002)(6666003)(6916009)(8656003)(110136004)(77096006)(4326008)(2351001)(106466001)(2950100002)(33646002)(16586007)(50466002)(104016004)(5890100001)(48376002)(85426001)(356003)(498600001)(189998001)(50226002)(81156014)(81166006)(47776003)(7416002)(76176999)(97736004)(36756003)(2906002)(1076002)(68736007)(8676002)(305945005)(15650500001)(54906002)(575784001)(8936002)(53936002)(86362001)(50986999)(5660300001)(5003940100001);\n\tDIR:OUT; SFP:1101; SCL:1; SRVR:CY1PR03MB2363;\n\tH:tx30smr01.am.freescale.net; \n\tFPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; ",
        "X-Microsoft-Exchange-Diagnostics": [
            "1; BL2FFO11FD008;\n\t1:7DZBxSpWg9x2HD+MIXSmw6AxmB9JhVMs4gycnB1OECpv4VM/zA1wX7Y+O+WqZTGaBFGi9yjf/Lw2dZTeYwzVNQxB+65+pIkcvg2E0fLhZgbHEwZwishGD6tR8Bn5dSnl",
            "1; CY1PR03MB2363;\n\t3:vCHeHa3NoVmtTKFDny7SMAye5XNPyUsiMAAA7O33SuBFpNGxGs74HhwNw540zn4yq1WTMHt1K5FgUqUoqZAx4AbYZkXoNRJD1k2OSQ5bC0qF7j66CcCLX6TdUJSwrOvULJjKUfhidObSTlEzU//kJOIn+6DKPbZ0vU3XPZiSgCW88P9NqmH8Q2Tl9FmA2kqklgg0tHKulQbWOsIDCqUMTHKa3E3c2iQGhuYEAYLQ6qaritQczLusg1rBaMZi+lJIbrlAvjHWDw25e4WxDkZf6tboAE/0Loc/g+GVQXk5wjre2kfheSsEYvKeH8690kiQVPzMgQKQvu18x5BKaBfhvRBCj+R8FZKEjZGT0RO62mA=;\n\t25:nAuHrHyatQmkJi2UM6eD5kRXvPvy4hk/vxg7gl066eJi1ufm3igQ9sA0X+cYjQIarhkrosToP/PAZ1h+nkz/tRhkZVqPpwEHu4QWccl6U0rEDptQ51sypZeX508P6AmdliJ70IWAcG3lSCM3wrvv1F9eEVUDTQnhsrEd8sz/0dRUH4cQvdp6+PQrqyakq+VtpfSr++734nQfYZiJygRBb48vdtb6Uycuf/F6Bhzz4/rxtZXLUiTpPCxMSmVnJx75aSJ9MM4ESixGXeBkCIYoL/MuLDB0eMKiw3n7BPR0TlZlqONNXuDxjtE25iooBZ5jMQ5q+oAzsAdfsIK+6ggwgw==",
            "1; CY1PR03MB2363;\n\t31:0krZBYa9qeDuFSdsEiPEtA878MBMH5sYaXbzNYk7p0p59M+q/y6OyUSmrl01h26blCL88T2sE7fedb3xWtGUCpPBaV+qCmlVCS8ygzsrX6wWI4jmRpQBumbI9Q2cEhp2WeyFKJ4vA32Ao2bYTKTVbgCyyHoJK/+FuHjL7cq5d3jeFeoXcFUBI8pyPquErj3wAehkPyBuMxA0+R9mZs/NRxwskcCvPoEq8JMGT7V7Gus=;\n\t4:Ufz/6hv7KXU37zJGwHJ947maAdxm3btH/9OkqcXY5/7juFnZ5GhooNCETN5zcLMF9MTKBDO9UAs2Fub5D9wTtialumGeH8BCWvXuuRkc6qU6nxaHf9HzuwQROQfMJrxuQkn/hRJBLmvghnfPGPlDPS/jrjPWl3xMtsBVlXCdWd9R3IPTDMscrQ3sMkuslwe1mb+kij8ldmf08mVuKLKpfdNnOWhzX3TN332f5fzjgTpr4dklNOGiY1qCqMAyyqmW9Io0bsd1EcBsyf50vdyMDd00NWLJ58glEx/zL/obMGUQO+TDNCWd0N8DEenPtVxVYLM8Voy3TT9uZGWa1pjegsz4ccc/gxaXR2DgtqsZ5uo=",
            "=?us-ascii?Q?1; CY1PR03MB2363;\n\t23:eHlroVI8wO9Lh/nogDAFiCxnvTElK+2TXdfeQ1FA1?=\n\tXbBEZY3/vXxgwTaN07lxk1uT6zRpl19U1LXFCyvSN0Sa0R6gWcq3CuU4GLbbaA8gsXdoMZIVALnJl3aBo/EjNolPbEyqQ9lEsO1HnAWLOSms+ugSeFn8MzsKdjK4XN6Ga+I2kx8aUX8QtSc9IndgZni8GqFaBoG3Obv+tYIpZ9ef19AwRxL5cnomYgZuF+XUnN0ROgbLNjtcHGRRwjvteyL+OIoM1PxqlwCtV4YfwInuyzgppRCfKo/QDqCBp6jlqY49xmXsAAPoieCHHaO/RnJNyM97vIBTGiQ5TlJvLJA4qw6/YRfauojgk2DI0wYZ3ol+nWrHnHWxcvBszEaBZol6Ye3bzb9li3oE4pxh4/LdK0psjKBfyBeSomMVCzTRG4e0CyZsqE4uwJsbn9Bw//Zdf44B+hF3awbh1EQ3JDJwX12EzTY7JwjMRdE3UbJCfAk3FWREd94yyLUeOw7PTA9pV/mzjI+nTMm0wUxTXqZtn3z+tMoD7kgDg3NW58qbEOHPw4gPe/OTTd1YNeg2mlwj3oyp0aKcF1VHHSYU1+T9UdkkHcIiMfJgfmiPChiZkdv360Q8U2Ou7nNVxK9tZtPSucuIybg9WAlV3V6YF7hPfRr3dH+5sqicQ5FoZ9MSHBO5q+X9IJcwyzUCttD0fIt2bR0xADQA8LTxoPcuvJcLd2bja348zws0H+PFK7jEEorEkVkQygwR8FTW4qUH+ofhTttTJj4eSxqDYwt4UPh3eXq4Sgdc0EUNUkZvNmHvvB7g3DORKSeMy7qvrBFL+JWIbRFY+fg63sJoFExvH5SCGTz6imuvq9J5Jx/8h4PvFJv4tCbyFW/LFXDUA8MOUD4ZG0Fz5XL3vUnJe2gpxPumMQTgZXT+2OW2Nr8hM4cosSIGgalssDFYFI+e48VVrC9fSl9XuiTvQFU66B5otZLiF7g75KdufzjRqC5lLBRLf7Cb1xH4iaehpnG5PIieOLIAhOfBxY7x07HOBj8I6HRctdZfYbP2v16AO+1T01F1yWjdfyxlZJq7bN004qD8gmB+zWV5zifRDsSb6N2rOYBj9vDRwNilUGsUt34w4qMlTv3FEGEo2IdGrdzu7wstRhPGw9HWTtX1hAgOgf3aRLYKTiNlN0JAUbzzrAMdB79iMNfb6v6oMbpKCxbkyi3OpcKPsHXVPq24oyHqgGu87ULR3uI3hnT2kAYyHEvmP05C0ENzjZI7SzSOKjGVmCLHr2NIyBk2oYZCniQzCBsKQgRAh54EJC/DX9BZKdmxAj9frg=",
            "1; CY1PR03MB2363;\n\t6:Qh054LHM4PV1DuDnjziGPLqGCOxcZisa40v4J9ULbaVaHFGGEBh7GbqMnDFQiSDtvRcja/aGD+3MqzohTHwhWm6hGeBLDlyAgZaoyUAd31VL9dwqCtuDUdLBBWKU3D6Y6ZBNhsUh9XWBEiYd6ohSrV/tk5tK1sU10qIKT7fY0BNCj16JSTZnHuwxYEOVxBSFbhui+oA0u5o1AKywIvaaPDA5QuPpeG74sWu+MhtWZnNRBvBSWDZKD6uJRSqId9zPK8kH3XKA1QYWqeDoEPdLIhi3GtdHcoIReOESoON4u9QRQnZtOBhbX++ie4QAdWEJLk+2u2qWG/cmq6iTR/Leeg==;\n\t5:3qvtcxmhakNOgTI13p0I3w/IxYFnzlMSgdqjwJ/HqC8XxnBjNLwkHk6gViAfolU9UEyFQLtjRgVrwlZJMKcnQPzUUU5tjb3cbO/b7xtrJCBbRSau10D4vEEh5UMoI2vackZ8mIky7OcrCi3xzdzvWA==;\n\t24:8HLDWoIs0+yt2zm3iXwt7xFS499NniGl71/VIBJRVu/PhfoKsiJu4r9XKgrzW552iMQ4/jXBE83qWf6RV7fwH97Ts7jfnxID8NIvOCIjVIg=;\n\t7:FfsL3drc6ldqzIK2flNdUbOQ2GrsuUtH+vm0dL4vY7lMU7/kKVH56B3ngB0WIZEXlaWbyKmWGmqOR5KHy4I31hr1NRJFKaE68XWOS+sL0u587Y03mW1U9HKvaJS1wwVntYxpumvB4I2KaDgk1mtCaGbm/+59wsCw00T8CCOrL+OXLk7kGyQ5RsVXT5HoznZYursmPpBZ6MC5LvXvZ/TIBd0q8FJ8AczDHRudtxkzy2g="
        ],
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-Office365-Filtering-Correlation-Id": "16f1f8f2-825b-4af1-ac1a-08d4fb4ac5c0",
        "X-Microsoft-Antispam": "UriScan:; BCL:0; PCL:0;\n\tRULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(300000503095)(300135400095)(2017052603199)(201703131430075)(201703131517081)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095);\n\tSRVR:CY1PR03MB2363; ",
        "X-MS-TrafficTypeDiagnostic": "CY1PR03MB2363:",
        "X-Exchange-Antispam-Report-Test": "UriScan:(192374486261705)(185117386973197)(228905959029699); ",
        "X-Microsoft-Antispam-PRVS": "<CY1PR03MB2363F2E660B1357F220AFBE6E66F0@CY1PR03MB2363.namprd03.prod.outlook.com>",
        "X-Exchange-Antispam-Report-CFA-Test": "BCL:0; PCL:0;\n\tRULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6095135)(2401047)(5005006)(8121501046)(3002001)(10201501046)(93006095)(93001095)(100000703101)(100105400095)(6055026)(6096035)(20161123565025)(20161123561025)(20161123556025)(201703131430075)(201703131448075)(201703131433075)(201703161259150)(201703151042153)(20161123559100)(20161123563025)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095);\n\tSRVR:CY1PR03MB2363; BCL:0; PCL:0;\n\tRULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(400006)(100000804101)(100110200095)(100000805101)(100110500095);\n\tSRVR:CY1PR03MB2363; ",
        "X-Forefront-PRVS": "0430FA5CB7",
        "SpamDiagnosticOutput": "1:99",
        "SpamDiagnosticMetadata": "NSPM",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "14 Sep 2017 08:29:52.8412\n\t(UTC)",
        "X-MS-Exchange-CrossTenant-Id": "5afe0b00-7697-4969-b663-5eab37d5f47e",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e;\n\tIp=[192.88.168.50]; \n\tHelo=[tx30smr01.am.freescale.net]",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "CY1PR03MB2363",
        "Subject": "[dpdk-dev] [PATCH 11/11] examples/ipsec-secgw: add support for\n\tsecurity offload",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "ipsec-secgw application is modified so that it can support\nfollowing type of actions for crypto operations\n1. full protocol offload using crypto devices.\n2. inline ipsec using ethernet devices to perform crypto operations\n3. full protocol offload using ethernet devices.\n4. non protocol offload\n\nSigned-off-by: Akhil Goyal <akhil.goyal@nxp.com>\nSigned-off-by: Radu Nicolau <radu.nicolau@intel.com>\nSigned-off-by: Boris Pismenny <borisp@mellanox.com>\nSigned-off-by: Declan Doherty <declan.doherty@intel.com>\n---\n doc/guides/sample_app_ug/ipsec_secgw.rst |  52 +++++-\n examples/ipsec-secgw/esp.c               | 101 ++++++++----\n examples/ipsec-secgw/esp.h               |  10 --\n examples/ipsec-secgw/ipsec-secgw.c       |   5 +\n examples/ipsec-secgw/ipsec.c             | 275 +++++++++++++++++++++++++------\n examples/ipsec-secgw/ipsec.h             |  32 +++-\n examples/ipsec-secgw/sa.c                | 151 +++++++++++++----\n 7 files changed, 498 insertions(+), 128 deletions(-)",
    "diff": "diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst\nindex b675cba..892977e 100644\n--- a/doc/guides/sample_app_ug/ipsec_secgw.rst\n+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst\n@@ -52,13 +52,22 @@ The application classifies the ports as *Protected* and *Unprotected*.\n Thus, traffic received on an Unprotected or Protected port is consider\n Inbound or Outbound respectively.\n \n+The application also supports complete IPSec protocol offload to hardware\n+(Look aside crypto accelarator or using ethernet device). It also support\n+inline ipsec processing by the supported ethernet device during transmission.\n+These modes can be selected during the SA creation configuration.\n+\n+In case of complete protocol offload, the processing of headers(ESP and outer\n+IP header) is done by the hardware and the application does not need to\n+add/remove them during outbound/inbound processing.\n+\n The Path for IPsec Inbound traffic is:\n \n *  Read packets from the port.\n *  Classify packets between IPv4 and ESP.\n *  Perform Inbound SA lookup for ESP packets based on their SPI.\n-*  Perform Verification/Decryption.\n-*  Remove ESP and outer IP header\n+*  Perform Verification/Decryption (Not needed in case of inline ipsec).\n+*  Remove ESP and outer IP header (Not needed in case of protocol offload).\n *  Inbound SP check using ACL of decrypted packets and any other IPv4 packets.\n *  Routing.\n *  Write packet to port.\n@@ -68,8 +77,8 @@ The Path for the IPsec Outbound traffic is:\n *  Read packets from the port.\n *  Perform Outbound SP check using ACL of all IPv4 traffic.\n *  Perform Outbound SA lookup for packets that need IPsec protection.\n-*  Add ESP and outer IP header.\n-*  Perform Encryption/Digest.\n+*  Add ESP and outer IP header (Not needed in case protocol offload).\n+*  Perform Encryption/Digest (Not needed in case of inline ipsec).\n *  Routing.\n *  Write packet to port.\n \n@@ -385,7 +394,7 @@ The SA rule syntax is shown as follows:\n .. code-block:: console\n \n     sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>\n-    <mode> <src_ip> <dst_ip>\n+    <mode> <src_ip> <dst_ip> <action_type> <port_id>\n \n where each options means:\n \n@@ -526,6 +535,34 @@ where each options means:\n    * *dst X.X.X.X* for IPv4\n    * *dst XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX* for IPv6\n \n+``<type>``\n+\n+ * Action type to specify the security action. This option specify\n+   the SA to be performed with look aside protocol offload to HW\n+   accelerator or protocol offload on ethernet device or inline\n+   crypto processing on the ethernet device during transmission.\n+\n+ * Optional: Yes, default type *no-offload*\n+\n+ * Available options:\n+\n+   * *lookaside-protocol-offload*: look aside protocol offload to HW accelerator\n+   * *inline-protocol-offload*: inline protocol offload on ethernet device\n+   * *inline-crypto-offload*: inline crypto processing on ethernet device\n+   * *no-offload*: no offloading to hardware\n+\n+ ``<port_id>``\n+\n+ * Port/device ID of the ethernet/crypto accelerator for which the SA is\n+   configured. This option is used when *type* is NOT *no-offload*\n+\n+ * Optional: No, if *type* is not *no-offload*\n+\n+ * Syntax:\n+\n+   * *port_id X* X is a valid device number in decimal\n+\n+\n Example SA rules:\n \n .. code-block:: console\n@@ -545,6 +582,11 @@ Example SA rules:\n     aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \\\n     mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5\n \n+    sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \\\n+    auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \\\n+    mode ipv4-tunnel src 172.16.1.5 dst 172.16.2.5 \\\n+    type lookaside-protocol-offload port_id 4\n+\n Routing rule syntax\n ^^^^^^^^^^^^^^^^^^^\n \ndiff --git a/examples/ipsec-secgw/esp.c b/examples/ipsec-secgw/esp.c\nindex 70bb81f..8fa6178 100644\n--- a/examples/ipsec-secgw/esp.c\n+++ b/examples/ipsec-secgw/esp.c\n@@ -58,8 +58,11 @@ esp_inbound(struct rte_mbuf *m, struct ipsec_sa *sa,\n \tstruct rte_crypto_sym_op *sym_cop;\n \tint32_t payload_len, ip_hdr_len;\n \n-\tRTE_ASSERT(m != NULL);\n \tRTE_ASSERT(sa != NULL);\n+\tif (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO)\n+\t\treturn 0;\n+\n+\tRTE_ASSERT(m != NULL);\n \tRTE_ASSERT(cop != NULL);\n \n \tip4 = rte_pktmbuf_mtod(m, struct ip *);\n@@ -175,29 +178,42 @@ esp_inbound_post(struct rte_mbuf *m, struct ipsec_sa *sa,\n \tRTE_ASSERT(sa != NULL);\n \tRTE_ASSERT(cop != NULL);\n \n+\tif (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {\n+\t\tif (m->ol_flags & PKT_RX_SEC_OFFLOAD\n+\t\t\t\t&& m->ol_flags & PKT_RX_SEC_OFFLOAD_FAILED)\n+\t\t\tcop->status = RTE_CRYPTO_OP_STATUS_ERROR;\n+\t\telse\n+\t\t\tcop->status = RTE_CRYPTO_OP_STATUS_SUCCESS;\n+\t}\n+\n \tif (cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {\n \t\tRTE_LOG(ERR, IPSEC_ESP, \"failed crypto op\\n\");\n \t\treturn -1;\n \t}\n \n-\tnexthdr = rte_pktmbuf_mtod_offset(m, uint8_t*,\n-\t\t\trte_pktmbuf_pkt_len(m) - sa->digest_len - 1);\n-\tpad_len = nexthdr - 1;\n+\tif (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO &&\n+\t    sa->sec_xform->options.no_trailer) {\n+\t\tnexthdr = &m->inner_esp_next_proto;\n+\t} else {\n+\t\tnexthdr = rte_pktmbuf_mtod_offset(m, uint8_t*,\n+\t\t\t\trte_pktmbuf_pkt_len(m) - sa->digest_len - 1);\n+\t\tpad_len = nexthdr - 1;\n+\n+\t\tpadding = pad_len - *pad_len;\n+\t\tfor (i = 0; i < *pad_len; i++) {\n+\t\t\tif (padding[i] != i + 1) {\n+\t\t\t\tRTE_LOG(ERR, IPSEC_ESP, \"invalid padding\\n\");\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t}\n \n-\tpadding = pad_len - *pad_len;\n-\tfor (i = 0; i < *pad_len; i++) {\n-\t\tif (padding[i] != i + 1) {\n-\t\t\tRTE_LOG(ERR, IPSEC_ESP, \"invalid padding\\n\");\n+\t\tif (rte_pktmbuf_trim(m, *pad_len + 2 + sa->digest_len)) {\n+\t\t\tRTE_LOG(ERR, IPSEC_ESP,\n+\t\t\t\t\t\"failed to remove pad_len + digest\\n\");\n \t\t\treturn -EINVAL;\n \t\t}\n \t}\n \n-\tif (rte_pktmbuf_trim(m, *pad_len + 2 + sa->digest_len)) {\n-\t\tRTE_LOG(ERR, IPSEC_ESP,\n-\t\t\t\t\"failed to remove pad_len + digest\\n\");\n-\t\treturn -EINVAL;\n-\t}\n-\n \tif (unlikely(sa->flags == TRANSPORT)) {\n \t\tip = rte_pktmbuf_mtod(m, struct ip *);\n \t\tip4 = (struct ip *)rte_pktmbuf_adj(m,\n@@ -226,14 +242,13 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,\n \tstruct ip *ip4;\n \tstruct ip6_hdr *ip6;\n \tstruct esp_hdr *esp = NULL;\n-\tuint8_t *padding, *new_ip, nlp;\n+\tuint8_t *padding = NULL, *new_ip, nlp;\n \tstruct rte_crypto_sym_op *sym_cop;\n \tint32_t i;\n-\tuint16_t pad_payload_len, pad_len, ip_hdr_len;\n+\tuint16_t pad_payload_len, pad_len = 0, ip_hdr_len;\n \n \tRTE_ASSERT(m != NULL);\n \tRTE_ASSERT(sa != NULL);\n-\tRTE_ASSERT(cop != NULL);\n \n \tip_hdr_len = 0;\n \n@@ -261,7 +276,6 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,\n \t/* Padded payload length */\n \tpad_payload_len = RTE_ALIGN_CEIL(rte_pktmbuf_pkt_len(m) -\n \t\t\tip_hdr_len + 2, sa->block_size);\n-\tpad_len = pad_payload_len + ip_hdr_len - rte_pktmbuf_pkt_len(m);\n \n \tRTE_ASSERT(sa->flags == IP4_TUNNEL || sa->flags == IP6_TUNNEL ||\n \t\t\tsa->flags == TRANSPORT);\n@@ -283,12 +297,21 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,\n \t\treturn -EINVAL;\n \t}\n \n-\tpadding = (uint8_t *)rte_pktmbuf_append(m, pad_len + sa->digest_len);\n-\tif (unlikely(padding == NULL)) {\n-\t\tRTE_LOG(ERR, IPSEC_ESP, \"not enough mbuf trailing space\\n\");\n-\t\treturn -ENOSPC;\n+\t/* Add trailer padding if it is not constructed by HW */\n+\tif (sa->type != RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||\n+\t    (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO &&\n+\t     !sa->sec_xform->options.no_trailer)) {\n+\t\tpad_len = pad_payload_len + ip_hdr_len - rte_pktmbuf_pkt_len(m);\n+\n+\t\tpadding = (uint8_t *)rte_pktmbuf_append(m, pad_len +\n+\t\t\t\t\t\t\tsa->digest_len);\n+\t\tif (unlikely(padding == NULL)) {\n+\t\t\tRTE_LOG(ERR, IPSEC_ESP,\n+\t\t\t\t\t\"not enough mbuf trailing space\\n\");\n+\t\t\treturn -ENOSPC;\n+\t\t}\n+\t\trte_prefetch0(padding);\n \t}\n-\trte_prefetch0(padding);\n \n \tswitch (sa->flags) {\n \tcase IP4_TUNNEL:\n@@ -321,8 +344,19 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,\n \tesp->spi = rte_cpu_to_be_32(sa->spi);\n \tesp->seq = rte_cpu_to_be_32((uint32_t)sa->seq);\n \n-\tuint64_t *iv = (uint64_t *)(esp + 1);\n+\tif (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {\n+\t\tif (sa->sec_xform->options.no_trailer) {\n+\t\t\t/* Set the inner esp next protocol for HW trailer */\n+\t\t\tm->inner_esp_next_proto = nlp;\n+\t\t} else {\n+\t\t\tpadding[pad_len - 2] = pad_len - 2;\n+\t\t\tpadding[pad_len - 1] = nlp;\n+\t\t}\n+\t\tgoto done;\n+\t}\n \n+\tRTE_ASSERT(cop != NULL);\n+\tuint64_t *iv = (uint64_t *)(esp + 1);\n \tsym_cop = get_sym_cop(cop);\n \tsym_cop->m_src = m;\n \n@@ -407,21 +441,26 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,\n \t\t\t\trte_pktmbuf_pkt_len(m) - sa->digest_len);\n \t}\n \n+done:\n \treturn 0;\n }\n \n int\n-esp_outbound_post(struct rte_mbuf *m __rte_unused,\n-\t\tstruct ipsec_sa *sa __rte_unused,\n-\t\tstruct rte_crypto_op *cop)\n+esp_outbound_post(struct rte_mbuf *m,\n+\t\t  struct ipsec_sa *sa,\n+\t\t  struct rte_crypto_op *cop)\n {\n \tRTE_ASSERT(m != NULL);\n \tRTE_ASSERT(sa != NULL);\n-\tRTE_ASSERT(cop != NULL);\n \n-\tif (cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {\n-\t\tRTE_LOG(ERR, IPSEC_ESP, \"Failed crypto op\\n\");\n-\t\treturn -1;\n+\tif (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {\n+\t\tm->ol_flags |= PKT_TX_SEC_OFFLOAD;\n+\t} else {\n+\t\tRTE_ASSERT(cop != NULL);\n+\t\tif (cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {\n+\t\t\tRTE_LOG(ERR, IPSEC_ESP, \"Failed crypto op\\n\");\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n \treturn 0;\ndiff --git a/examples/ipsec-secgw/esp.h b/examples/ipsec-secgw/esp.h\nindex fa5cc8a..23601e3 100644\n--- a/examples/ipsec-secgw/esp.h\n+++ b/examples/ipsec-secgw/esp.h\n@@ -35,16 +35,6 @@\n \n struct mbuf;\n \n-/* RFC4303 */\n-struct esp_hdr {\n-\tuint32_t spi;\n-\tuint32_t seq;\n-\t/* Payload */\n-\t/* Padding */\n-\t/* Pad Length */\n-\t/* Next Header */\n-\t/* Integrity Check Value - ICV */\n-};\n \n int\n esp_inbound(struct rte_mbuf *m, struct ipsec_sa *sa,\ndiff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c\nindex 99dc270..da18e88 100644\n--- a/examples/ipsec-secgw/ipsec-secgw.c\n+++ b/examples/ipsec-secgw/ipsec-secgw.c\n@@ -1357,6 +1357,11 @@ port_init(uint8_t portid)\n \tprintf(\"Creating queues: nb_rx_queue=%d nb_tx_queue=%u...\\n\",\n \t\t\tnb_rx_queue, nb_tx_queue);\n \n+\tif (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SECURITY)\n+\t\tport_conf.rxmode.enable_sec = 1;\n+\tif (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SECURITY)\n+\t\tport_conf.txmode.enable_sec = 1;\n+\n \tret = rte_eth_dev_configure(portid, nb_rx_queue, nb_tx_queue,\n \t\t\t&port_conf);\n \tif (ret < 0)\ndiff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c\nindex 0afb9d6..3d241a2 100644\n--- a/examples/ipsec-secgw/ipsec.c\n+++ b/examples/ipsec-secgw/ipsec.c\n@@ -37,7 +37,9 @@\n #include <rte_branch_prediction.h>\n #include <rte_log.h>\n #include <rte_crypto.h>\n+#include <rte_security.h>\n #include <rte_cryptodev.h>\n+#include <rte_ethdev.h>\n #include <rte_mbuf.h>\n #include <rte_hash.h>\n \n@@ -49,7 +51,7 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)\n {\n \tstruct rte_cryptodev_info cdev_info;\n \tunsigned long cdev_id_qp = 0;\n-\tint32_t ret;\n+\tint32_t ret = 0;\n \tstruct cdev_key key = { 0 };\n \n \tkey.lcore_id = (uint8_t)rte_lcore_id();\n@@ -57,13 +59,16 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)\n \tkey.cipher_algo = (uint8_t)sa->cipher_algo;\n \tkey.auth_algo = (uint8_t)sa->auth_algo;\n \n-\tret = rte_hash_lookup_data(ipsec_ctx->cdev_map, &key,\n-\t\t\t(void **)&cdev_id_qp);\n-\tif (ret < 0) {\n-\t\tRTE_LOG(ERR, IPSEC, \"No cryptodev: core %u, cipher_algo %u, \"\n+\tif (sa->type == RTE_SECURITY_ACTION_TYPE_NONE) {\n+\t\tret = rte_hash_lookup_data(ipsec_ctx->cdev_map, &key,\n+\t\t\t\t(void **)&cdev_id_qp);\n+\t\tif (ret < 0) {\n+\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\t\"No cryptodev: core %u, cipher_algo %u, \"\n \t\t\t\t\"auth_algo %u\\n\", key.lcore_id, key.cipher_algo,\n \t\t\t\tkey.auth_algo);\n-\t\treturn -1;\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n \tRTE_LOG_DP(DEBUG, IPSEC, \"Create session for SA spi %u on cryptodev \"\n@@ -71,23 +76,130 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)\n \t\t\tipsec_ctx->tbl[cdev_id_qp].id,\n \t\t\tipsec_ctx->tbl[cdev_id_qp].qp);\n \n-\tsa->crypto_session = rte_cryptodev_sym_session_create(\n-\t\t\tipsec_ctx->session_pool);\n-\trte_cryptodev_sym_session_init(ipsec_ctx->tbl[cdev_id_qp].id,\n-\t\t\tsa->crypto_session, sa->xforms,\n-\t\t\tipsec_ctx->session_pool);\n-\n-\trte_cryptodev_info_get(ipsec_ctx->tbl[cdev_id_qp].id, &cdev_info);\n-\tif (cdev_info.sym.max_nb_sessions_per_qp > 0) {\n-\t\tret = rte_cryptodev_queue_pair_attach_sym_session(\n-\t\t\t\tipsec_ctx->tbl[cdev_id_qp].id,\n-\t\t\t\tipsec_ctx->tbl[cdev_id_qp].qp,\n-\t\t\t\tsa->crypto_session);\n-\t\tif (ret < 0) {\n-\t\t\tRTE_LOG(ERR, IPSEC,\n-\t\t\t\t\"Session cannot be attached to qp %u \",\n-\t\t\t\tipsec_ctx->tbl[cdev_id_qp].qp);\n-\t\t\treturn -1;\n+\tif (sa->type != RTE_SECURITY_ACTION_TYPE_NONE) {\n+\t\tstruct rte_security_session_conf sess_conf = {\n+\t\t\t.action_type = sa->type,\n+\t\t\t.protocol = RTE_SECURITY_PROTOCOL_IPSEC,\n+\t\t\t.ipsec = {\n+\t\t\t\t.spi = sa->spi,\n+\t\t\t\t.salt = sa->salt,\n+\t\t\t\t.options = { 0 },\n+\t\t\t\t.direction = sa->direction,\n+\t\t\t\t.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,\n+\t\t\t\t.mode = (sa->flags == IP4_TUNNEL ||\n+\t\t\t\t\t\tsa->flags == IP6_TUNNEL) ?\n+\t\t\t\t\tRTE_SECURITY_IPSEC_SA_MODE_TUNNEL :\n+\t\t\t\t\tRTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,\n+\t\t\t},\n+\t\t\t.crypto_xform = sa->xforms\n+\n+\t\t};\n+\n+\t\tif (sess_conf.ipsec.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {\n+\t\t\tstruct rte_security_ipsec_tunnel_param *tunnel =\n+\t\t\t\t\t&sess_conf.ipsec.tunnel;\n+\n+\t\t\tif (sa->flags == IP4_TUNNEL) {\n+\t\t\t\ttunnel->type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;\n+\t\t\t\ttunnel->ipv4.ttl = IPDEFTTL;\n+\n+\t\t\t\tmemcpy((uint8_t *)&tunnel->ipv4.src_ip,\n+\t\t\t\t\t\t(uint8_t *)&sa->src.ip.ip4, 4);\n+\n+\t\t\t\tmemcpy((uint8_t *)&tunnel->ipv4.dst_ip,\n+\t\t\t\t\t\t(uint8_t *)&sa->dst.ip.ip4, 4);\n+\t\t\t}\n+\t\t\t/* TODO support for Transport and IPV6 tunnel */\n+\t\t}\n+\n+\t\tif (sa->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) {\n+\t\t\tsa->sec_session = rte_security_session_create(\n+\t\t\t\t\trte_cryptodev_get_sec_id(\n+\t\t\t\t\tipsec_ctx->tbl[cdev_id_qp].id),\n+\t\t\t\t\t&sess_conf, ipsec_ctx->session_pool);\n+\t\t\tif (sa->sec_session == NULL) {\n+\t\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\t\"SEC Session init failed: err: %d\", ret);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t} else if (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {\n+\t\t\tstruct rte_eth_dev_info dev_info;\n+\t\t\tstruct rte_flow_error err;\n+\n+\t\t\tsa->sec_session = rte_security_session_create(\n+\t\t\t\t\trte_eth_dev_get_sec_id(sa->portid),\n+\t\t\t\t\t&sess_conf, ipsec_ctx->session_pool);\n+\t\t\tif (sa->sec_session == NULL) {\n+\t\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\t\"SEC Session init failed: err: %d\", ret);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\n+\t\t\trte_eth_dev_info_get(sa->portid, &dev_info);\n+\t\t\tif (dev_info.tx_offload_capa &\n+\t\t\t\t\tDEV_TX_OFFLOAD_SEC_NEED_MDATA) {\n+\t\t\t\tsa->port_needs_md = 1;\n+\t\t\t\tsa->port_md_uid =\n+\t\t\t\t\trte_eth_dev_get_sec_id(sa->portid);\n+\t\t\t}\n+\n+\t\t\tsa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;\n+\n+\t\t\tsa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;\n+\t\t\tsa->pattern[1].mask = &rte_flow_item_ipv4_mask;\n+\t\t\tif (sa->flags & IP6_TUNNEL) {\n+\t\t\t\tsa->pattern[1].spec = &sa->ipv6_spec;\n+\t\t\t\tmemcpy(sa->ipv6_spec.hdr.dst_addr,\n+\t\t\t\t\tsa->dst.ip.ip6.ip6_b, 16);\n+\t\t\t\tmemcpy(sa->ipv6_spec.hdr.src_addr,\n+\t\t\t\t       sa->src.ip.ip6.ip6_b, 16);\n+\t\t\t} else {\n+\t\t\t\tsa->pattern[1].spec = &sa->ipv4_spec;\n+\t\t\t\tsa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;\n+\t\t\t\tsa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;\n+\t\t\t}\n+\n+\t\t\tsa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;\n+\t\t\tsa->pattern[2].spec = &sa->esp_spec;\n+\t\t\tsa->pattern[2].mask = &rte_flow_item_esp_mask;\n+\t\t\tsa->esp_spec.hdr.spi = sa->spi;\n+\n+\t\t\tsa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;\n+\n+\t\t\tsa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;\n+\t\t\tsa->action[0].conf = sa->sec_session;\n+\n+\t\t\tsa->action[1].type = RTE_FLOW_ACTION_TYPE_END;\n+\n+\t\t\tsa->flow = rte_flow_create(sa->portid,\n+\t\t\t\t&sa->attr, sa->pattern, sa->action, &err);\n+\t\t\tif (sa->flow == NULL) {\n+\t\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\t\t\"Failed to create ipsec flow msg: %s\\n\",\n+\t\t\t\t\terr.message);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\tsa->crypto_session = rte_cryptodev_sym_session_create(\n+\t\t\t\tipsec_ctx->session_pool);\n+\t\trte_cryptodev_sym_session_init(ipsec_ctx->tbl[cdev_id_qp].id,\n+\t\t\t\tsa->crypto_session, sa->xforms,\n+\t\t\t\tipsec_ctx->session_pool);\n+\n+\t\trte_cryptodev_info_get(ipsec_ctx->tbl[cdev_id_qp].id,\n+\t\t\t\t&cdev_info);\n+\t\tif (cdev_info.sym.max_nb_sessions_per_qp > 0) {\n+\t\t\tret = rte_cryptodev_queue_pair_attach_sym_session(\n+\t\t\t\t\tipsec_ctx->tbl[cdev_id_qp].id,\n+\t\t\t\t\tipsec_ctx->tbl[cdev_id_qp].qp,\n+\t\t\t\t\tsa->crypto_session);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\t\t\"Session cannot be attached to qp %u \",\n+\t\t\t\t\tipsec_ctx->tbl[cdev_id_qp].qp);\n+\t\t\t\treturn -1;\n+\t\t\t}\n \t\t}\n \t}\n \tsa->cdev_id_qp = cdev_id_qp;\n@@ -125,7 +237,9 @@ ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n {\n \tint32_t ret = 0, i;\n \tstruct ipsec_mbuf_metadata *priv;\n+\tstruct rte_crypto_sym_op *sym_cop;\n \tstruct ipsec_sa *sa;\n+\tstruct cdev_qp *cqp;\n \n \tfor (i = 0; i < nb_pkts; i++) {\n \t\tif (unlikely(sas[i] == NULL)) {\n@@ -140,23 +254,76 @@ ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n \t\tsa = sas[i];\n \t\tpriv->sa = sa;\n \n-\t\tpriv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;\n-\t\tpriv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;\n-\n-\t\trte_prefetch0(&priv->sym_cop);\n-\n-\t\tif ((unlikely(sa->crypto_session == NULL)) &&\n-\t\t\t\tcreate_session(ipsec_ctx, sa)) {\n-\t\t\trte_pktmbuf_free(pkts[i]);\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\trte_crypto_op_attach_sym_session(&priv->cop,\n-\t\t\t\tsa->crypto_session);\n-\n-\t\tret = xform_func(pkts[i], sa, &priv->cop);\n-\t\tif (unlikely(ret)) {\n-\t\t\trte_pktmbuf_free(pkts[i]);\n+\t\tswitch (sa->type) {\n+\t\tcase RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL:\n+\t\t\tpriv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;\n+\t\t\tpriv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;\n+\n+\t\t\trte_prefetch0(&priv->sym_cop);\n+\n+\t\t\tif ((unlikely(sa->sec_session == NULL)) &&\n+\t\t\t\t\tcreate_session(ipsec_ctx, sa)) {\n+\t\t\t\trte_pktmbuf_free(pkts[i]);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tsym_cop = get_sym_cop(&priv->cop);\n+\t\t\tsym_cop->m_src = pkts[i];\n+\n+\t\t\trte_security_attach_session(&priv->cop,\n+\t\t\t\t\tsa->sec_session);\n+\t\t\tbreak;\n+\t\tcase RTE_SECURITY_ACTION_TYPE_NONE:\n+\n+\t\t\tpriv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;\n+\t\t\tpriv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;\n+\n+\t\t\trte_prefetch0(&priv->sym_cop);\n+\n+\t\t\tif ((unlikely(sa->crypto_session == NULL)) &&\n+\t\t\t\t\tcreate_session(ipsec_ctx, sa)) {\n+\t\t\t\trte_pktmbuf_free(pkts[i]);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\trte_crypto_op_attach_sym_session(&priv->cop,\n+\t\t\t\t\tsa->crypto_session);\n+\n+\t\t\tret = xform_func(pkts[i], sa, &priv->cop);\n+\t\t\tif (unlikely(ret)) {\n+\t\t\t\trte_pktmbuf_free(pkts[i]);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:\n+\t\t\tbreak;\n+\t\tcase RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:\n+\t\t\tpriv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;\n+\t\t\tpriv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;\n+\n+\t\t\trte_prefetch0(&priv->sym_cop);\n+\n+\t\t\tif ((unlikely(sa->sec_session == NULL)) &&\n+\t\t\t\t\tcreate_session(ipsec_ctx, sa)) {\n+\t\t\t\trte_pktmbuf_free(pkts[i]);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\trte_security_attach_session(&priv->cop,\n+\t\t\t\t\tsa->sec_session);\n+\n+\t\t\tret = xform_func(pkts[i], sa, &priv->cop);\n+\t\t\tif (unlikely(ret)) {\n+\t\t\t\trte_pktmbuf_free(pkts[i]);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tcqp = &ipsec_ctx->tbl[sa->cdev_id_qp];\n+\t\t\tcqp->ol_pkts[cqp->ol_pkts_cnt++] = pkts[i];\n+\t\t\tif (sa->port_needs_md)\n+\t\t\t\trte_security_set_pkt_metadata(\n+\t\t\t\t\t\tsa->port_md_uid,\n+\t\t\t\t\t\tsa->sec_session, pkts[i], NULL);\n \t\t\tcontinue;\n \t\t}\n \n@@ -167,7 +334,7 @@ ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n \n static inline int\n ipsec_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n-\t\tstruct rte_mbuf *pkts[], uint16_t max_pkts)\n+\t      struct rte_mbuf *pkts[], uint16_t max_pkts)\n {\n \tint32_t nb_pkts = 0, ret = 0, i, j, nb_cops;\n \tstruct ipsec_mbuf_metadata *priv;\n@@ -182,6 +349,19 @@ ipsec_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n \t\tif (ipsec_ctx->last_qp == ipsec_ctx->nb_qps)\n \t\t\tipsec_ctx->last_qp %= ipsec_ctx->nb_qps;\n \n+\t\twhile (cqp->ol_pkts_cnt > 0 && nb_pkts < max_pkts) {\n+\t\t\tpkt = cqp->ol_pkts[--cqp->ol_pkts_cnt];\n+\t\t\trte_prefetch0(pkt);\n+\t\t\tpriv = get_priv(pkt);\n+\t\t\tsa = priv->sa;\n+\t\t\tret = xform_func(pkt, sa, &priv->cop);\n+\t\t\tif (unlikely(ret)) {\n+\t\t\t\trte_pktmbuf_free(pkt);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tpkts[nb_pkts++] = pkt;\n+\t\t}\n+\n \t\tif (cqp->in_flight == 0)\n \t\t\tcontinue;\n \n@@ -199,11 +379,14 @@ ipsec_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n \n \t\t\tRTE_ASSERT(sa != NULL);\n \n-\t\t\tret = xform_func(pkt, sa, cops[j]);\n-\t\t\tif (unlikely(ret))\n-\t\t\t\trte_pktmbuf_free(pkt);\n-\t\t\telse\n-\t\t\t\tpkts[nb_pkts++] = pkt;\n+\t\t\tif (sa->type == RTE_SECURITY_ACTION_TYPE_NONE) {\n+\t\t\t\tret = xform_func(pkt, sa, cops[j]);\n+\t\t\t\tif (unlikely(ret)) {\n+\t\t\t\t\trte_pktmbuf_free(pkt);\n+\t\t\t\t\tcontinue;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tpkts[nb_pkts++] = pkt;\n \t\t}\n \t}\n \ndiff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h\nindex da1fb1b..34d31f5 100644\n--- a/examples/ipsec-secgw/ipsec.h\n+++ b/examples/ipsec-secgw/ipsec.h\n@@ -38,6 +38,8 @@\n \n #include <rte_byteorder.h>\n #include <rte_crypto.h>\n+#include <rte_security.h>\n+#include <rte_flow.h>\n \n #define RTE_LOGTYPE_IPSEC       RTE_LOGTYPE_USER1\n #define RTE_LOGTYPE_IPSEC_ESP   RTE_LOGTYPE_USER2\n@@ -99,7 +101,10 @@ struct ipsec_sa {\n \tuint32_t cdev_id_qp;\n \tuint64_t seq;\n \tuint32_t salt;\n-\tstruct rte_cryptodev_sym_session *crypto_session;\n+\tunion {\n+\t\tstruct rte_cryptodev_sym_session *crypto_session;\n+\t\tstruct rte_security_session *sec_session;\n+\t};\n \tenum rte_crypto_cipher_algorithm cipher_algo;\n \tenum rte_crypto_auth_algorithm auth_algo;\n \tenum rte_crypto_aead_algorithm aead_algo;\n@@ -117,7 +122,28 @@ struct ipsec_sa {\n \tuint8_t auth_key[MAX_KEY_SIZE];\n \tuint16_t auth_key_len;\n \tuint16_t aad_len;\n-\tstruct rte_crypto_sym_xform *xforms;\n+\tunion {\n+\t\tstruct rte_crypto_sym_xform *xforms;\n+\t\tstruct rte_security_ipsec_xform *sec_xform;\n+\t};\n+\tenum rte_security_session_action_type type;\n+\tenum rte_security_ipsec_sa_direction direction;\n+\tuint16_t portid;\n+\tuint8_t port_needs_md;\n+\tuid_t port_md_uid;\n+\n+#define MAX_RTE_FLOW_PATTERN (4)\n+#define MAX_RTE_FLOW_ACTIONS (2)\n+\tstruct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];\n+\tstruct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];\n+\tstruct rte_flow_attr attr;\n+\tunion {\n+\t\tstruct rte_flow_item_ipv4 ipv4_spec;\n+\t\tstruct rte_flow_item_ipv6 ipv6_spec;\n+\t};\n+\tstruct rte_flow_item_esp esp_spec;\n+\tstruct rte_flow *flow;\n+\tstruct rte_security_session_conf sess_conf;\n } __rte_cache_aligned;\n \n struct ipsec_mbuf_metadata {\n@@ -133,6 +159,8 @@ struct cdev_qp {\n \tuint16_t in_flight;\n \tuint16_t len;\n \tstruct rte_crypto_op *buf[MAX_PKT_BURST] __rte_aligned(sizeof(void *));\n+\tstruct rte_mbuf *ol_pkts[MAX_PKT_BURST] __rte_aligned(sizeof(void *));\n+\tuint16_t ol_pkts_cnt;\n };\n \n struct ipsec_ctx {\ndiff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c\nindex 7be0e62..1f8739d 100644\n--- a/examples/ipsec-secgw/sa.c\n+++ b/examples/ipsec-secgw/sa.c\n@@ -41,16 +41,20 @@\n \n #include <rte_memzone.h>\n #include <rte_crypto.h>\n+#include <rte_security.h>\n #include <rte_cryptodev.h>\n #include <rte_byteorder.h>\n #include <rte_errno.h>\n #include <rte_ip.h>\n #include <rte_random.h>\n+#include <rte_ethdev.h>\n \n #include \"ipsec.h\"\n #include \"esp.h\"\n #include \"parser.h\"\n \n+#define IPDEFTTL 64\n+\n struct supported_cipher_algo {\n \tconst char *keyword;\n \tenum rte_crypto_cipher_algorithm algo;\n@@ -238,6 +242,8 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,\n \tuint32_t src_p = 0;\n \tuint32_t dst_p = 0;\n \tuint32_t mode_p = 0;\n+\tuint32_t type_p = 0;\n+\tuint32_t portid_p = 0;\n \n \tif (strcmp(tokens[0], \"in\") == 0) {\n \t\tri = &nb_sa_in;\n@@ -550,6 +556,52 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,\n \t\t\tcontinue;\n \t\t}\n \n+\t\tif (strcmp(tokens[ti], \"type\") == 0) {\n+\t\t\tAPP_CHECK_PRESENCE(type_p, tokens[ti], status);\n+\t\t\tif (status->status < 0)\n+\t\t\t\treturn;\n+\n+\t\t\tINCREMENT_TOKEN_INDEX(ti, n_tokens, status);\n+\t\t\tif (status->status < 0)\n+\t\t\t\treturn;\n+\n+\t\t\tif (strcmp(tokens[ti], \"inline-crypto-offload\") == 0)\n+\t\t\t\trule->type =\n+\t\t\t\t\tRTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO;\n+\t\t\telse if (strcmp(tokens[ti],\n+\t\t\t\t\t\"inline-protocol-offload\") == 0)\n+\t\t\t\trule->type =\n+\t\t\t\tRTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL;\n+\t\t\telse if (strcmp(tokens[ti],\n+\t\t\t\t\t\"lookaside-protocol-offload\") == 0)\n+\t\t\t\trule->type =\n+\t\t\t\tRTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;\n+\t\t\telse if (strcmp(tokens[ti], \"no-offload\") == 0)\n+\t\t\t\trule->type = RTE_SECURITY_ACTION_TYPE_NONE;\n+\t\t\telse {\n+\t\t\t\tAPP_CHECK(0, status, \"Invalid input \\\"%s\\\"\",\n+\t\t\t\t\t\ttokens[ti]);\n+\t\t\t\treturn;\n+\t\t\t}\n+\n+\t\t\ttype_p = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(tokens[ti], \"port_id\") == 0) {\n+\t\t\tAPP_CHECK_PRESENCE(portid_p, tokens[ti], status);\n+\t\t\tif (status->status < 0)\n+\t\t\t\treturn;\n+\t\t\tINCREMENT_TOKEN_INDEX(ti, n_tokens, status);\n+\t\t\tif (status->status < 0)\n+\t\t\t\treturn;\n+\t\t\trule->portid = atoi(tokens[ti]);\n+\t\t\tif (status->status < 0)\n+\t\t\t\treturn;\n+\t\t\tportid_p = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\t/* unrecognizeable input */\n \t\tAPP_CHECK(0, status, \"unrecognized input \\\"%s\\\"\",\n \t\t\ttokens[ti]);\n@@ -580,6 +632,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,\n \tif (status->status < 0)\n \t\treturn;\n \n+\tif ((rule->type != RTE_SECURITY_ACTION_TYPE_NONE) && (portid_p == 0))\n+\t\tprintf(\"Missing portid option, falling back to non-offload\");\n+\n+\tif (!type_p || !portid_p) {\n+\t\trule->type = RTE_SECURITY_ACTION_TYPE_NONE;\n+\t\trule->portid = -1;\n+\t}\n+\n \t*ri = *ri + 1;\n }\n \n@@ -647,9 +707,11 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)\n \n struct sa_ctx {\n \tstruct ipsec_sa sa[IPSEC_SA_MAX_ENTRIES];\n-\tstruct {\n-\t\tstruct rte_crypto_sym_xform a;\n-\t\tstruct rte_crypto_sym_xform b;\n+\tunion {\n+\t\tstruct {\n+\t\t\tstruct rte_crypto_sym_xform a;\n+\t\t\tstruct rte_crypto_sym_xform b;\n+\t\t};\n \t} xf[IPSEC_SA_MAX_ENTRIES];\n };\n \n@@ -682,6 +744,33 @@ sa_create(const char *name, int32_t socket_id)\n }\n \n static int\n+check_eth_dev_caps(uint16_t portid, uint32_t inbound)\n+{\n+\tstruct rte_eth_dev_info dev_info;\n+\n+\trte_eth_dev_info_get(portid, &dev_info);\n+\n+\tif (inbound) {\n+\t\tif ((dev_info.rx_offload_capa &\n+\t\t\t\tDEV_RX_OFFLOAD_SECURITY) == 0) {\n+\t\t\tRTE_LOG(WARNING, PORT,\n+\t\t\t\t\"hardware RX IPSec offload is not supported\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t} else { /* outbound */\n+\t\tif ((dev_info.tx_offload_capa &\n+\t\t\t\tDEV_TX_OFFLOAD_SECURITY) == 0) {\n+\t\t\tRTE_LOG(WARNING, PORT,\n+\t\t\t\t\"hardware TX IPSec offload is not supported\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+\n+static int\n sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n \t\tuint32_t nb_entries, uint32_t inbound)\n {\n@@ -700,6 +789,16 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n \t\t*sa = entries[i];\n \t\tsa->seq = 0;\n \n+\t\tif (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||\n+\t\t\tsa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {\n+\t\t\tif (check_eth_dev_caps(sa->portid, inbound))\n+\t\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tsa->direction = (inbound == 1) ?\n+\t\t\t\tRTE_SECURITY_IPSEC_SA_DIR_INGRESS :\n+\t\t\t\tRTE_SECURITY_IPSEC_SA_DIR_EGRESS;\n+\n \t\tswitch (sa->flags) {\n \t\tcase IP4_TUNNEL:\n \t\t\tsa->src.ip.ip4 = rte_cpu_to_be_32(sa->src.ip.ip4);\n@@ -709,37 +808,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n \t\tif (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {\n \t\t\tiv_length = 16;\n \n-\t\t\tif (inbound) {\n-\t\t\t\tsa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.algo = sa->aead_algo;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.key.data = sa->cipher_key;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.key.length =\n-\t\t\t\t\tsa->cipher_key_len;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.op =\n-\t\t\t\t\tRTE_CRYPTO_AEAD_OP_DECRYPT;\n-\t\t\t\tsa_ctx->xf[idx].a.next = NULL;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.iv.offset = IV_OFFSET;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.iv.length = iv_length;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.aad_length =\n-\t\t\t\t\tsa->aad_len;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.digest_length =\n-\t\t\t\t\tsa->digest_len;\n-\t\t\t} else { /* outbound */\n-\t\t\t\tsa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.algo = sa->aead_algo;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.key.data = sa->cipher_key;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.key.length =\n-\t\t\t\t\tsa->cipher_key_len;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.op =\n-\t\t\t\t\tRTE_CRYPTO_AEAD_OP_ENCRYPT;\n-\t\t\t\tsa_ctx->xf[idx].a.next = NULL;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.iv.offset = IV_OFFSET;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.iv.length = iv_length;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.aad_length =\n-\t\t\t\t\tsa->aad_len;\n-\t\t\t\tsa_ctx->xf[idx].a.aead.digest_length =\n-\t\t\t\t\tsa->digest_len;\n-\t\t\t}\n+\t\t\tsa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;\n+\t\t\tsa_ctx->xf[idx].a.aead.algo = sa->aead_algo;\n+\t\t\tsa_ctx->xf[idx].a.aead.key.data = sa->cipher_key;\n+\t\t\tsa_ctx->xf[idx].a.aead.key.length =\n+\t\t\t\tsa->cipher_key_len;\n+\t\t\tsa_ctx->xf[idx].a.aead.op = (inbound == 1) ?\n+\t\t\t\tRTE_CRYPTO_AEAD_OP_DECRYPT :\n+\t\t\t\tRTE_CRYPTO_AEAD_OP_ENCRYPT;\n+\t\t\tsa_ctx->xf[idx].a.next = NULL;\n+\t\t\tsa_ctx->xf[idx].a.aead.iv.offset = IV_OFFSET;\n+\t\t\tsa_ctx->xf[idx].a.aead.iv.length = iv_length;\n+\t\t\tsa_ctx->xf[idx].a.aead.aad_length =\n+\t\t\t\tsa->aad_len;\n+\t\t\tsa_ctx->xf[idx].a.aead.digest_length =\n+\t\t\t\tsa->digest_len;\n \n \t\t\tsa->xforms = &sa_ctx->xf[idx].a;\n \n",
    "prefixes": [
        "dpdk-dev",
        "11/11"
    ]
}