From patchwork Tue Mar 27 07:54:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shahaf Shuler X-Patchwork-Id: 891413 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=Mellanox.com header.i=@Mellanox.com header.b="tsoNNRzo"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 409NdK2TGtz9ryG for ; Tue, 27 Mar 2018 18:56:53 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id EB94F1667; Tue, 27 Mar 2018 07:55:51 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 92A381326 for ; Tue, 27 Mar 2018 07:55:49 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from EUR01-DB5-obe.outbound.protection.outlook.com (mail-db5eur01on0088.outbound.protection.outlook.com [104.47.2.88]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 6D3CB51F for ; Tue, 27 Mar 2018 07:55:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=lt1o8aNVsajZOwoeYqTuWNFZT5HcN/OeVFU+5pebyGs=; b=tsoNNRzokQPhfYaDW8q+qbRJ2a91UEeRWLZYlOiakfeLiUcXn4ymUA5fNiM3mBrUfTMSxaqmsny1sBIVdYLk/eTt6h96yO4DVeNKMRhwBpeWy+4t6ZnfRtv2MMjFNuURuXGbl5FVeIG1DtHgt40o3VsX1ECA3+BUMiOcccBTQY0= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=shahafs@mellanox.com; Received: from mellanox.com (141.226.120.58) by AM0PR05MB4418.eurprd05.prod.outlook.com (2603:10a6:208:5a::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.609.10; Tue, 27 Mar 2018 07:55:43 +0000 From: Shahaf Shuler To: fc@napatech.com, ian.stokes@intel.com Date: Tue, 27 Mar 2018 10:54:43 +0300 Message-Id: X-Mailer: git-send-email 2.12.0 In-Reply-To: References: <1517209188-16608-2-git-send-email-yliu@fridaylinux.org> MIME-Version: 1.0 X-Originating-IP: [141.226.120.58] X-ClientProxiedBy: DB6PR1001CA0041.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:4:55::27) To AM0PR05MB4418.eurprd05.prod.outlook.com (2603:10a6:208:5a::15) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: d9fc0925-44f0-4c89-0fd8-08d593b824bb X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(48565401081)(5600026)(4604075)(4534165)(4627221)(201703031133081)(201702281549075)(2017052603328)(7153060)(7193020); SRVR:AM0PR05MB4418; X-Microsoft-Exchange-Diagnostics: 1; AM0PR05MB4418; 3:lWuH0qXCcTIy+j89q4VcZn14Uu5P95hLO5mEV4SrSMi0Hw+RFF2DBS6REWQC70V8DyFBM629iLLU8hkCbfokT31yWe6E9j/iOQFubrqcUVFdHOWH+0+YSrz/5Jnkz6gR1Y1fxgfVhRpQLyTK0Jxem+1pIB6pDvZGLIqeUpNVcC3gpus+p3ohsa+kzwQgHi2lfyw4hPPOGWvF105uX+UW2IPDxUcTriI9H+B9ClDATDIqOgrrDHHRvdph27F5oq9d; 25:+rnPCGgQWcuSID4MZPAhIHlE8ctBh711Nq8q93l2IOUkr+67MmSfjaEHRRpMee4fFBE2DSJWzfVXOfBM9Kt1ikId9LCwh6X1wTZ2lYSIXkKPmLemm/axwNioS56l+mSQqYI8vo5BZepYO2dy6slhxomk2Xqv//ck63TP2wwZevkgsW3mUMBmJ0kHHAqQGjSrw22Njd4B9+V+BAydjXMFlVBfkcxHY119yGp/VmZru2lSgJbkc0EUVjwSdHua9qSMxZHi2ZDmIjwaQyiFsjd522gf+OygL+q1ARDXd1al35faZx0Q0p+eDISRp655/6F956T/KHY7xJzZiO3L4lUkmA==; 31:b2mqHvW952DvWQfDPqA3mdKACkpfNKU3z4LPV5iXSz+O9/qf+MnK4Q+LhLoKQ7CaoP6M/SBprwQr5oTYYW6zft68x9iBTCyYsXnfIPs+mVEGsr/uO5BBAiLu5EnjrJ3gvjbzXfQ3fUlkiX3gqkeR1trilENqqZSUW/kfYLSeFM3nAlrHRDufo3T+lQ81I+C6rkYK561IbkPLIkboohjYxpZ1MD0z3xkP+lK3xcqP71E= X-MS-TrafficTypeDiagnostic: AM0PR05MB4418: X-Microsoft-Exchange-Diagnostics: 1; AM0PR05MB4418; 20:s/r2ZzM+QFVBPUwCocjM2V/bodoq2uE5oTFcLb2au9K0LtFDNB5inzUfVwsiulgcH4gfOYdUpNgzdsfiJaSjmel/fnaRVpEDBE7cQ6nqrSQDqn2ZM8ztu/B0zjVWLbzvqzjQAk4nOlMPbhP/1rvKFV+jkJ6n/aqebuoj87oYJCaX661TSHLSxlU/4WDZPVuTlPxyvE1iUIMPTOoOpNTeA2T34WLx6dgitMOmBM3BmNMczlDP8eLBeypWBTp31Nxyb7+9AWK2cxV4P35f5HNlbN65gcxKoGhcYvj8Qy81Wm7zRDQm0SdLtMzv2gLFbb53dG46n1BQ5tebORcHdpq7O6f25sRxNIoT9wkB8VTdzwFjyGtaICVzIA9sygyb3IWO4AGSrx4MApOxxRjvG6fUqXa5AL1B0UZOSD0sqF0N2Qyd6hGhup847dcktL0BeJh49rIK3GoIakerszR+A/ztU8Tx7ppBcY8/sbmJRU5IDVk1pzPhBk2YaAufT1XLnmhn; 4:9scBURBaBM3MUuNwu97DH8rwTm6a+9+zSBfL751LrzfbUXwZ/IisvwC0BYp6VKeNypdde2tXiwmMV2KoVrtv3/fgmOb85xvsE6RZf8DB0UuJfb9XJQ6RTwdeGr+MzLr433IC3iIfnLP8Rl3OyEoLYFwQXQOMDFzpbPPP/hsLGhIQhzPprS5JVQa0GmXwe05KXwfJbF4qGdtuKsvyHL9i0xInRL0vH+ivU5vHd1lhBgRYCIq8e32Pivr9xVd+6t0N62WGZZP7NiQDKU57Uwr1BQ== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(10201501046)(93006095)(93001095)(3002001)(3231221)(944501327)(52105095)(6055026)(6041310)(20161123564045)(20161123558120)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123562045)(6072148)(201708071742011); SRVR:AM0PR05MB4418; BCL:0; PCL:0; RULEID:; SRVR:AM0PR05MB4418; X-Forefront-PRVS: 0624A2429E X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(39860400002)(366004)(39380400002)(376002)(396003)(199004)(189003)(50226002)(7736002)(68736007)(3846002)(36756003)(6116002)(7696005)(50466002)(51416003)(21086003)(52116002)(59450400001)(386003)(76176011)(118296001)(16586007)(97736004)(8936002)(486005)(956004)(486005)(478600001)(305945005)(39060400002)(8676002)(25786009)(4326008)(48376002)(186003)(86362001)(26005)(316002)(106356001)(69596002)(16526019)(81156014)(55016002)(2906002)(81166006)(66066001)(105586002)(5660300001)(11346002)(2616005)(53936002)(47776003)(476003)(446003); DIR:OUT; SFP:1101; SCL:1; SRVR:AM0PR05MB4418; H:mellanox.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: mellanox.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; AM0PR05MB4418; 23:jTGgPRAJelgr9dZaDZG25wMB9fkyCG8ePuDasCyIg?= qhZDmrstn9qS/XSOVJzBvWc4j7LKWnvECs3BfDIfrRWI7ZNhpI4RyIiO7dUYU9Hso99xRwsUtCs+hBD7Ko6vfAk0cslnrsePF4pF/xjkFb76xY9xTQoWwgUTcHHBol78jXfyISH6e64iYsU8v4zjLsMvOsPPZI+sPXwc78VbJuVP+/gQ3uE2KfsMCEqBf6IGskqDKNJBJu6EM6Fkdk5ZLaSmnJikLTtI02DhaSr65J8hv+7FfwqbsgkUEPgX9VO+kksNpEqCl4Ax6FLa/ZDSpXgzC8P6J8wxQaHR0LhTxV/jk+PesNKmri9hdZQ8pcaenKocrbs7FHsucLySPlShohUzrzAkXiZ12LRmWjUR8ANIfnjJOh1/mjqSxZRPzRcq37aeDlq4h1Z1Ti4O8WO6fJqVsYEzFhWmo5PdZSnFRPVumzjNyVdmoRRpcrmggCKdIq2LoNjWtgJZMy3ljxpme4DOz1bo+W8O6+Vt6AsR8Lt6tkYqiDjsmzUdvTAs8m6afoU7VrTLX1BCRFcbFjSdmjzC6BJHKNN7m53A7oVagiYXY6yCgSsePJZtHDuPdMhSTLgLMBRxmEnFqHQ9ZlNIR/1QkZU1iDB3maqJNxb7yoLS18S/8Qf53zgKGYiLoQ7eDLzCkZm7at5ujyJp850ynkLcT4ps/eJIBxKN746wDqbo3sbwZAWtG45ijDAbuhCqMABqLOimgCvEcfpVBFMOO1qebuMeZgQe5AqNR30h9O4rxKTw4e7UES52uVCxtzSStDEfdyL1jlQ07rNnNb6/aVvIlO88dGZa2gSfhpW1m0yBua4FXs0jfQuapHC0CkM5fShjmUuHZ+3LXYF7KUV61IRYcc6OClerPWE7KKmX01YtZZ2iDjeo75LkrByM5EZLvEXGdr8c/CoxkYlvUcrgp7TmXfehsqs1zvQbs05x8SSRb/Iycu3kNPLSjOwuc/8N1oOrGuWGEjxAPy7TL/vzl0w6aLV/dDopu+GEU8b/gD7ajirJ0LCfcAZ0rxkNVB+BIxnDxh/WZE7YBIgrXIp6viJH9+6/g829+AjZ2vylZLsoDy0S9YFHgvTrV9yQ/BRi7q/DIQnbXR1iiXnLwcXVXiqwBIC7x80DAYMXsPjymnCp365KsZLKJSwXw/LDqzSYRK8VLyKZTu6DTWWjKIL062F+m2lmpMsbzy6lppGspUm0ZMHHm/m80h+vulmFAjvFq4= X-Microsoft-Antispam-Message-Info: 9LAG30AV7ekrJIGOAtvs4+i+9LDb13b6kmxAB0nRVgura9UEannBqrlqIoBcbRT0d9XoYnva7hWXbho3VW9R6HEgjV4NfYjcbNLBFOn5a6+N/nQiRtAoOb9B+HC3Kg9daSctzzhplbLieVDSfWHTDzmve4gN4svWn+mfd/eUpLAu9yng582ZnVEDjRpBr4rX X-Microsoft-Exchange-Diagnostics: 1; AM0PR05MB4418; 6:8pdJDdB0h2KkvExeciPN/ZR4lDE12ATtxdSywdD5pYufJDGrINnMBlTW9sZR9//O+yJdTD0YEtyoDU1U6DISJ8pcCRgieecc6S3MMgFBywAQAMvdEpEkyzaRlPi3P56y3OSoJXcmQ0k471CdFbldLeSvAPiYmKFDa3Zh3rN61DrTu80IjGmnBn7kBuWJRBR6ajp4kUFeWequwpUR1wWRgaPoSu3r3yfi0vaHUwU0OdDB4maq2VYDz2QWw/OEnYlPXaZ5jZdeJMYWTxTKhy1ftp15XeKvPZ+CmQ1YxJ+tQOitYYsCEHYlGiPgN2iHrcN6Hlcgzy1gt9ii4GJDWG0V9DWOGzb5QmWYEpSsnQfTH+THKsA39d+beXrwq76kqxCx07iOoRf0sBsl/JiVelgMH9/me6JJEtKTbL1CcR7+kgHyj69bWwSpW9UZ5Ti6rfM3c/Pk5NkbhpkhvEbx5SVIsA==; 5:SMmi+rkDwXU1P0dTeQPHEy3pWKTBxqLBdloJaknz1T2PJ2GGrDCAKxXWpuGqOIKu9tufYxctFef6do1QsyARLO01bvhLhREslkLjRoMQxhpjntBJa0W+ZNweArj5o7/cRU6RQSrB+E75smobG85JpXuPN9g55jXmL6hWCesPf3c=; 24:Lr6Gqd2y3CSYcLVWAHtoA0q0eOnfL6RTMmj1SNxL8+PZebekpJTAZ9/ZU2Nd03XHJdJXqCAnp8eoWlE8qYIB8CM/ZVTcQY/iKRZIXPUP2Ac= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; AM0PR05MB4418; 7:xPMt1sGUqB90W8Heh4PiZegRxAVNJ783XlFPSQHzx4+GGI1LjupadbIg7AxKnTcVqCBhny4xGu2BEIBTtTFqwvFBftFNsu+GIQBv008a62rhe4U6u7GMrDS0Bqvj8Kw+TRlw3lf/kUUQJhoLf2FgSpoe0KFSfIhGxw5B5m7U3UXuG5KPFvPD31pcgDNsuAk4gfhQRKaK/XPQkyfC+qcIVjOpi+lz2D9q2qYhM7ul6DWKyt0u1UAfSPwcUmtcv3+O X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Mar 2018 07:55:43.3235 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d9fc0925-44f0-4c89-0fd8-08d593b824bb X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR05MB4418 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: simon.horman@netronome.com, ovs-dev@openvswitch.org Subject: [ovs-dev] [PATCH v8 2/6] dpif-netdev: retrieve flow directly from the flow mark X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Yuanhan Liu So that we could skip some very costly CPU operations, including but not limiting to miniflow_extract, emc lookup, dpcls lookup, etc. Thus, performance could be greatly improved. A PHY-PHY forwarding with 1000 mega flows (udp,tp_src=1000-1999) and 1 million streams (tp_src=1000-1999, tp_dst=2000-2999) show more that 260% performance boost. Note that though the heavy miniflow_extract is skipped, we still have to do per packet checking, due to we have to check the tcp_flags. Co-authored-by: Finn Christensen Signed-off-by: Yuanhan Liu Signed-off-by: Finn Christensen Signed-off-by: Shahaf Shuler --- lib/dp-packet.h | 13 +++++ lib/dpif-netdev.c | 44 ++++++++++++-- lib/flow.c | 155 +++++++++++++++++++++++++++++++++++++++---------- lib/flow.h | 1 + 4 files changed, 175 insertions(+), 38 deletions(-) diff --git a/lib/dp-packet.h b/lib/dp-packet.h index 21c8ca5..dd3f17b 100644 --- a/lib/dp-packet.h +++ b/lib/dp-packet.h @@ -691,6 +691,19 @@ reset_dp_packet_checksum_ol_flags(struct dp_packet *p) #define reset_dp_packet_checksum_ol_flags(arg) #endif +static inline bool +dp_packet_has_flow_mark(struct dp_packet *p OVS_UNUSED, + uint32_t *mark OVS_UNUSED) +{ +#ifdef DPDK_NETDEV + if (p->mbuf.ol_flags & PKT_RX_FDIR_ID) { + *mark = p->mbuf.hash.fdir.hi; + return true; + } +#endif + return false; +} + enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets in a batch. */ struct dp_packet_batch { diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 2fdb6ef..7489a2f 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -2015,6 +2015,23 @@ flow_mark_flush(struct dp_netdev_pmd_thread *pmd) } } +static struct dp_netdev_flow * +mark_to_flow_find(const struct dp_netdev_pmd_thread *pmd, + const uint32_t mark) +{ + struct dp_netdev_flow *flow; + + CMAP_FOR_EACH_WITH_HASH (flow, mark_node, hash_int(mark, 0), + &flow_mark.mark_to_flow) { + if (flow->mark == mark && flow->pmd_id == pmd->core_id && + flow->dead == false) { + return flow; + } + } + + return NULL; +} + static void dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd, struct dp_netdev_flow *flow) @@ -5204,10 +5221,10 @@ struct packet_batch_per_flow { static inline void packet_batch_per_flow_update(struct packet_batch_per_flow *batch, struct dp_packet *packet, - const struct miniflow *mf) + uint16_t tcp_flags) { batch->byte_count += dp_packet_size(packet); - batch->tcp_flags |= miniflow_get_tcp_flags(mf); + batch->tcp_flags |= tcp_flags; batch->array.packets[batch->array.count++] = packet; } @@ -5241,7 +5258,7 @@ packet_batch_per_flow_execute(struct packet_batch_per_flow *batch, static inline void dp_netdev_queue_batches(struct dp_packet *pkt, - struct dp_netdev_flow *flow, const struct miniflow *mf, + struct dp_netdev_flow *flow, uint16_t tcp_flags, struct packet_batch_per_flow *batches, size_t *n_batches) { @@ -5252,7 +5269,7 @@ dp_netdev_queue_batches(struct dp_packet *pkt, packet_batch_per_flow_init(batch, flow); } - packet_batch_per_flow_update(batch, pkt, mf); + packet_batch_per_flow_update(batch, pkt, tcp_flags); } /* Try to process all ('cnt') the 'packets' using only the exact match cache @@ -5283,6 +5300,7 @@ emc_processing(struct dp_netdev_pmd_thread *pmd, const size_t cnt = dp_packet_batch_size(packets_); uint32_t cur_min; int i; + uint16_t tcp_flags; atomic_read_relaxed(&pmd->dp->emc_insert_min, &cur_min); pmd_perf_update_counter(&pmd->perf_stats, @@ -5291,6 +5309,7 @@ emc_processing(struct dp_netdev_pmd_thread *pmd, DP_PACKET_BATCH_REFILL_FOR_EACH (i, cnt, packet, packets_) { struct dp_netdev_flow *flow; + uint32_t mark; if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) { dp_packet_delete(packet); @@ -5298,6 +5317,16 @@ emc_processing(struct dp_netdev_pmd_thread *pmd, continue; } + if (dp_packet_has_flow_mark(packet, &mark)) { + flow = mark_to_flow_find(pmd, mark); + if (flow) { + tcp_flags = parse_tcp_flags(packet); + dp_netdev_queue_batches(packet, flow, tcp_flags, batches, + n_batches); + continue; + } + } + if (i != cnt - 1) { struct dp_packet **packets = packets_->packets; /* Prefetch next packet data and metadata. */ @@ -5323,7 +5352,8 @@ emc_processing(struct dp_netdev_pmd_thread *pmd, flow = NULL; } if (OVS_LIKELY(flow)) { - dp_netdev_queue_batches(packet, flow, &key->mf, batches, + tcp_flags = miniflow_get_tcp_flags(&key->mf); + dp_netdev_queue_batches(packet, flow, tcp_flags, batches, n_batches); } else { /* Exact match cache missed. Group missed packets together at @@ -5501,7 +5531,9 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd, flow = dp_netdev_flow_cast(rules[i]); emc_probabilistic_insert(pmd, &keys[i], flow); - dp_netdev_queue_batches(packet, flow, &keys[i].mf, batches, n_batches); + dp_netdev_queue_batches(packet, flow, + miniflow_get_tcp_flags(&keys[i].mf), + batches, n_batches); } pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_MASKED_HIT, diff --git a/lib/flow.c b/lib/flow.c index 38ff29c..6c74dd3 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -624,6 +624,70 @@ flow_extract(struct dp_packet *packet, struct flow *flow) miniflow_expand(&m.mf, flow); } +static inline bool +ipv4_sanity_check(const struct ip_header *nh, size_t size, + int *ip_lenp, uint16_t *tot_lenp) +{ + int ip_len; + uint16_t tot_len; + + if (OVS_UNLIKELY(size < IP_HEADER_LEN)) { + return false; + } + ip_len = IP_IHL(nh->ip_ihl_ver) * 4; + + if (OVS_UNLIKELY(ip_len < IP_HEADER_LEN || size < ip_len)) { + return false; + } + + tot_len = ntohs(nh->ip_tot_len); + if (OVS_UNLIKELY(tot_len > size || ip_len > tot_len || + size - tot_len > UINT8_MAX)) { + return false; + } + + *ip_lenp = ip_len; + *tot_lenp = tot_len; + + return true; +} + +static inline uint8_t +ipv4_get_nw_frag(const struct ip_header *nh) +{ + uint8_t nw_frag = 0; + + if (OVS_UNLIKELY(IP_IS_FRAGMENT(nh->ip_frag_off))) { + nw_frag = FLOW_NW_FRAG_ANY; + if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) { + nw_frag |= FLOW_NW_FRAG_LATER; + } + } + + return nw_frag; +} + +static inline bool +ipv6_sanity_check(const struct ovs_16aligned_ip6_hdr *nh, size_t size) +{ + uint16_t plen; + + if (OVS_UNLIKELY(size < sizeof *nh)) { + return false; + } + + plen = ntohs(nh->ip6_plen); + if (OVS_UNLIKELY(plen > size)) { + return false; + } + /* Jumbo Payload option not supported yet. */ + if (OVS_UNLIKELY(size - plen > UINT8_MAX)) { + return false; + } + + return true; +} + /* Caller is responsible for initializing 'dst' with enough storage for * FLOW_U64S * 8 bytes. */ void @@ -748,22 +812,7 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst) int ip_len; uint16_t tot_len; - if (OVS_UNLIKELY(size < IP_HEADER_LEN)) { - goto out; - } - ip_len = IP_IHL(nh->ip_ihl_ver) * 4; - - if (OVS_UNLIKELY(ip_len < IP_HEADER_LEN)) { - goto out; - } - if (OVS_UNLIKELY(size < ip_len)) { - goto out; - } - tot_len = ntohs(nh->ip_tot_len); - if (OVS_UNLIKELY(tot_len > size || ip_len > tot_len)) { - goto out; - } - if (OVS_UNLIKELY(size - tot_len > UINT8_MAX)) { + if (OVS_UNLIKELY(!ipv4_sanity_check(nh, size, &ip_len, &tot_len))) { goto out; } dp_packet_set_l2_pad_size(packet, size - tot_len); @@ -786,31 +835,19 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst) nw_tos = nh->ip_tos; nw_ttl = nh->ip_ttl; nw_proto = nh->ip_proto; - if (OVS_UNLIKELY(IP_IS_FRAGMENT(nh->ip_frag_off))) { - nw_frag = FLOW_NW_FRAG_ANY; - if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) { - nw_frag |= FLOW_NW_FRAG_LATER; - } - } + nw_frag = ipv4_get_nw_frag(nh); data_pull(&data, &size, ip_len); } else if (dl_type == htons(ETH_TYPE_IPV6)) { - const struct ovs_16aligned_ip6_hdr *nh; + const struct ovs_16aligned_ip6_hdr *nh = data; ovs_be32 tc_flow; uint16_t plen; - if (OVS_UNLIKELY(size < sizeof *nh)) { + if (OVS_UNLIKELY(!ipv6_sanity_check(nh, size))) { goto out; } - nh = data_pull(&data, &size, sizeof *nh); + data_pull(&data, &size, sizeof *nh); plen = ntohs(nh->ip6_plen); - if (OVS_UNLIKELY(plen > size)) { - goto out; - } - /* Jumbo Payload option not supported yet. */ - if (OVS_UNLIKELY(size - plen > UINT8_MAX)) { - goto out; - } dp_packet_set_l2_pad_size(packet, size - plen); size = plen; /* Never pull padding. */ @@ -982,6 +1019,60 @@ parse_dl_type(const struct eth_header *data_, size_t size) return parse_ethertype(&data, &size); } +uint16_t +parse_tcp_flags(struct dp_packet *packet) +{ + const void *data = dp_packet_data(packet); + size_t size = dp_packet_size(packet); + ovs_be16 dl_type; + uint8_t nw_frag = 0, nw_proto = 0; + + if (packet->packet_type != htonl(PT_ETH)) { + return 0; + } + + data_pull(&data, &size, ETH_ADDR_LEN * 2); + dl_type = parse_ethertype(&data, &size); + if (OVS_LIKELY(dl_type == htons(ETH_TYPE_IP))) { + const struct ip_header *nh = data; + int ip_len; + uint16_t tot_len; + + if (OVS_UNLIKELY(!ipv4_sanity_check(nh, size, &ip_len, &tot_len))) { + return 0; + } + nw_proto = nh->ip_proto; + nw_frag = ipv4_get_nw_frag(nh); + + size = tot_len; /* Never pull padding. */ + data_pull(&data, &size, ip_len); + } else if (dl_type == htons(ETH_TYPE_IPV6)) { + const struct ovs_16aligned_ip6_hdr *nh = data; + + if (OVS_UNLIKELY(!ipv6_sanity_check(nh, size))) { + return 0; + } + data_pull(&data, &size, sizeof *nh); + + size = ntohs(nh->ip6_plen); /* Never pull padding. */ + if (!parse_ipv6_ext_hdrs__(&data, &size, &nw_proto, &nw_frag)) { + return 0; + } + nw_proto = nh->ip6_nxt; + } else { + return 0; + } + + if (!(nw_frag & FLOW_NW_FRAG_LATER) && nw_proto == IPPROTO_TCP && + size >= TCP_HEADER_LEN) { + const struct tcp_header *tcp = data; + + return TCP_FLAGS_BE32(tcp->tcp_ctl); + } + + return 0; +} + /* For every bit of a field that is wildcarded in 'wildcards', sets the * corresponding bit in 'flow' to zero. */ void diff --git a/lib/flow.h b/lib/flow.h index 770a07a..0adecbf 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -132,6 +132,7 @@ bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto, uint8_t *nw_frag); ovs_be16 parse_dl_type(const struct eth_header *data_, size_t size); bool parse_nsh(const void **datap, size_t *sizep, struct ovs_key_nsh *key); +uint16_t parse_tcp_flags(struct dp_packet *packet); static inline uint64_t flow_get_xreg(const struct flow *flow, int idx)