From patchwork Mon Oct 30 05:00:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nobuhiro MIKI X-Patchwork-Id: 1856815 X-Patchwork-Delegate: i.maximets@samsung.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=yahoo-corp.jp header.i=@yahoo-corp.jp header.a=rsa-sha256 header.s=selector1 header.b=JaBMf5XH; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SJh1T0VkBz1yQK for ; Mon, 30 Oct 2023 16:00:59 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 284804F363; Mon, 30 Oct 2023 05:00:57 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 284804F363 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key, unprotected) header.d=yahoo-corp.jp header.i=@yahoo-corp.jp header.a=rsa-sha256 header.s=selector1 header.b=JaBMf5XH X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pR9rVrLykuzl; Mon, 30 Oct 2023 05:00:55 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id 86B594F359; Mon, 30 Oct 2023 05:00:54 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 86B594F359 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 33337C0071; Mon, 30 Oct 2023 05:00:54 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id C3490C0032 for ; Mon, 30 Oct 2023 05:00:52 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 781E2853D3 for ; Mon, 30 Oct 2023 05:00:52 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 781E2853D3 Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key, unprotected) header.d=yahoo-corp.jp header.i=@yahoo-corp.jp header.a=rsa-sha256 header.s=selector1 header.b=JaBMf5XH X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7nrlQEFoVLqH for ; Mon, 30 Oct 2023 05:00:50 +0000 (UTC) Received: from corp-ob08.yahoo-corp.jp (corp-ob08.yahoo-corp.jp [183.79.94.93]) by smtp1.osuosl.org (Postfix) with ESMTPS id 1C61985350 for ; Mon, 30 Oct 2023 05:00:49 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 1C61985350 Received: from JPN01-OS0-obe.outbound.protection.outlook.com (mail-os0jpn01lp2105.outbound.protection.outlook.com [104.47.23.105]) by corp-ob08.yahoo-corp.jp (Postfix) with ESMTPS id 1B31019FB180 for ; Mon, 30 Oct 2023 14:00:47 +0900 (JST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=iqkoU6fdUHJoeeTR1SW1sZ7yZ9U4hJlXmaALLueI1Jb7N7GNjHEMLczWc3yIOwUAMZt7veIKPVN7GhH/31EW5HaPIXhVN5RIyircdBnNyEd0Da8n2PhXB4vVGqmpsr3eB1Ds44kCmU3gqklLgG4OoyoiP+h2xWsEWsZySWIaznv5QtVDWNLG+Hw1pQLDqdAFIYp2RHYVLA0v2HCHAFuFeC1g6C38yWxozeW9YQhSUWNHotAuMq9UOZFKpRZghX6UtfLprCQQwyJ3yFmYQ5FPAinOWBT6cTRbpWP6tMsj700SsfnPX/QR4xLbhpbIgog4bcu8nJ/Qpe3IgKhU2f2n7Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=3+ZSpYFEtNnFRAycLhGtdfXstUSuasBGZNHkctInGrw=; b=lMcTP9Woqkvy/FlhojubcHT6hdLL9tsNUGqvy3r9HHlOpTyCAu6o7dgOCxpetCpxeks1jeRqqxPPADyaCB7AXatr/V051MadOf/ofdhA8EEH8MKAdlPT+axeqYmF6Ye1v6Ifs8ms2KUnIIQaAf/xja+1cZ21ZjdqGYW0btY0DZaKmNGBnwJeN46lsVZGEuilBzwPsE3Vssp5AVz3Jg/Ubou1eMPovQPe14GCutiHPCoDKT9l9PnBJ0XK5EOLF6A3Ed4EzPsO/J52VJYKMl4CN7mN4DmJS8oqg4gIl7GaLX2D5PWI82jaSKxQ2tRBqdN5huy2kqe/Dp8eyroPcGCLcg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=yahoo-corp.jp; dmarc=pass action=none header.from=yahoo-corp.jp; dkim=pass header.d=yahoo-corp.jp; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo-corp.jp; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=3+ZSpYFEtNnFRAycLhGtdfXstUSuasBGZNHkctInGrw=; b=JaBMf5XHTCEIa8kH3tyoVODkLuNzTpZkqXQ9u9QsTYUneXmGEGnuGlH9dCdyDLwXfcxict9lSdwSabR2Ldui5jpnrB91g8Zoz9dT+Nh3VM2cRJOAT8U+QGv84lKRzWLO0wB9vJ7IztYd5OaKPgIv0OSAq+x+FNFI5Uug94vlX5o= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=yahoo-corp.jp; Received: from TYAPR01MB4109.jpnprd01.prod.outlook.com (2603:1096:404:c4::10) by OS0PR01MB5826.jpnprd01.prod.outlook.com (2603:1096:604:bb::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6933.19; Mon, 30 Oct 2023 05:00:45 +0000 Received: from TYAPR01MB4109.jpnprd01.prod.outlook.com ([fe80::c099:e345:ebe5:d3be]) by TYAPR01MB4109.jpnprd01.prod.outlook.com ([fe80::c099:e345:ebe5:d3be%6]) with mapi id 15.20.6933.024; Mon, 30 Oct 2023 05:00:45 +0000 From: Nobuhiro MIKI To: dev@openvswitch.org Date: Mon, 30 Oct 2023 14:00:04 +0900 Message-Id: <20231030050004.52658-1-nmiki@yahoo-corp.jp> X-Mailer: git-send-email 2.38.1 X-ClientProxiedBy: TYCPR01CA0081.jpnprd01.prod.outlook.com (2603:1096:405:3::21) To TYAPR01MB4109.jpnprd01.prod.outlook.com (2603:1096:404:c4::10) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: TYAPR01MB4109:EE_|OS0PR01MB5826:EE_ X-MS-Office365-Filtering-Correlation-Id: 499a90e8-2f43-4fbd-5533-08dbd9052bef X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: fuqSEr9nU/ua47hsKG7j+Z+DOj7B37IFjL3rFHsORJd+7h5kWDfKl0zuMJFX5mVpRyL27vjC5tjEqBGsJ10QKawwySwq/bOEDe8TL2rp0NwAWgxrLXuLh4LIn7kq4Ml67P/zP1Id1EG+0WPusRrQYZrnUr2o/AHKg6+PRdTeYFBwJe2fSBGaitIhhPn07rO0wEGWYxi7R6ti5633Zs7/HYyvZCCAvn0OB5UFMY7OuKV+UnPw7CMl6U7tW4bi29PXWPVUV3Ppgy75AYSgxw30ZXzj84gy8te3KaAJeec1AFr+JRfykaa4lXKLbU39PDr8wSphXiMdE7d6DUEVCcwB542eEdvklmyVPGD9TRK/W9cR5ieTIFdJWhW4eV+N0XsSuPXYY8AKS7opsI9kSeoMfzbC4+F/Gr+78y98kG6gZ2fpaquN3zOexfzUUCA7pU1I0lq/CR/haaB/vbrRTEQqo/IHeI1gysCpN8NmAVEMOxYF8WoAgSBKGzk1Y53iLqLfrwGzfmXwivBZnoOIjvxj4e9SK3rKwOI6G/CYFONeOVsZFCTPvg6wmEOjowZdPffdeOnD8s4yPWNK6f1UHznCwmcc40EvJDf9+LSHUCaHeohQyAchmZYtNH3tqegCVgX3fzw0743WhWvPjMGu8LWcCfBXdL54TdmA+Br+/O5oSCU= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:TYAPR01MB4109.jpnprd01.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(346002)(396003)(366004)(39860400002)(376002)(136003)(230922051799003)(230273577357003)(230173577357003)(64100799003)(186009)(1800799009)(451199024)(2616005)(1076003)(38100700002)(36756003)(107886003)(26005)(6512007)(6506007)(52116002)(83380400001)(38350700005)(82960400001)(66574015)(6486002)(30864003)(8676002)(8936002)(41300700001)(4326008)(86362001)(6916009)(316002)(5660300002)(2906002)(6666004)(66556008)(478600001)(66946007)(66476007); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: t3t45jsaRoDzKa3XbqVzgMYdnpdb7zp5hk8BB2j9+ORtG4/zwmbM5Mdvre0Nz0I9Z+cbh3KnaQbZPHzTMYoLF4u2Dpciy8vIerG+yjlHWEW2JXoZcKBHlInYLUSGXmKnml3uUvWcd4/Eb3woyvdyQJynaDTonELCn71R0lkfs5m763zKEP3zIMBfUxOh0sZIboIGuacEqoq1rpGBz5x8w6iJE2ZTx9xq/q5PwK4n8Z+4KOYMxDJWYsfuNNJYr9jYJip3N5jJ2Zk3M6z5sOELiuuMGvHwGDXWlHgZJCrtlfnb3PPkYjD3NYr9dSNFw6KxLHCOKQgcTePkMx4yy05P9ff7dOcuo74ZSV5RkyYxlpW271OJHIBJdLcCGPva5jJbNpNvwKyCtH/xE8zBGBZXj8IKC/fSHgY2w94dptreJzMQqWkWHzMiOmP7gzlsF/t4jNwd89Cl1Kthjy77ng1zT3w6Rf1IX5OjSdQURB59yzJj++xUYzdEh/Ozm67vv7gQJ9fWpn4QGY2e3EInHUjnID5UfMaPU4c1LT6hWC+7XsuTUnTbG5tucDHoQfls8lxZmxmC8vHuNk93QMS4pxQLL0DONmpMA48hdg5jjETYz2ydiy+hJhrxr8UVjHdI9741wWQMR2/i0X/QNilbyLh4v9lS+Mo2WSyCaliPFQvAaJKnQAdEw9EUoMwFdGVJ56OMVSs/Ko9qPn7UBnBAXhungiyQG71v93Jc9HyTh3tmNmCoh8gfPiTFhRpppe0sYKON3iAws+gFOPLY+maI7ryzyAAMI9sGrFIU97QzvRf53mDqvgNytwk74QF701tKhfoQgu7drYGd0r+VJM7kKLwwVIdfW9DJIWd08JK5NRF9PG085SC1RNLPg1nOH0GtAYm9sCBvEHjjZgSaE7fA6FnBYjMzvaFs0VAIjCqnlTqMcuEfZEaPcJxlkcsDsA0Rr9bZ/Fc8xQtZSPwJG6IGTSX453D60CBTcHdKusiXy9Lb5ibwTmP8ysdiRPouQoKowH2TxkQp9uYcP8ADiFbn+MpZ1bQUXQrccSkYtg4wGslV6xrCeIALGWyEFKEdK8t3cB0XKQhxQ1/FCp0+ux3chcvQZWhv9PZy7cz8ZOzHrzR83Wwls1uM0QAEw734j67WbbwWFRkGbcCUwlPMPKYbW/rpxEAOHFLx/nlr/ieMyM21Twrq7ztfkqF1hIhnT4CoZfxft0snKxgKB898fVaBsuV3a61rZRaAq0cQRCdUaazrmckpqpHNajYExXPKD3/E2HowT9pqEXb3RgVXf9knF4pkdFF3W0uHH2rZXZSZXAXnGA9NwJcssTqOc5JJO6KNg3L/6EBl2uSvf1TrVU5KFTJAGY1UyhQb4mjd4aqR9jNgG0PkwNeRi1OhISHMcVh46gB5DMHpITaPShszRdkNQff13JeBX6mCilRo5xWvkLvFrQA5ewJxYfa+tYplvAoT2CrgL9g7bKwHFFcFpbSw5gD3enN49zF7V+I354SIkpjQ1HuI+xt5y5bchR29S17dsoCJycTe+XK3XEAKrNdWrRWHOlD5Zcv2bL6GH++IvnWONDu+FwoUjPm8KMySGVTklp/R X-OriginatorOrg: yahoo-corp.jp X-MS-Exchange-CrossTenant-Network-Message-Id: 499a90e8-2f43-4fbd-5533-08dbd9052bef X-MS-Exchange-CrossTenant-AuthSource: TYAPR01MB4109.jpnprd01.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Oct 2023 05:00:44.9658 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a208d369-cd4e-4f87-b119-98eaf31df2c3 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: oW+CW3oTZ6yzZklIwILVEKRku4/Feaf5WnPGlGV0Cx6k+G7Yvs+EiO2PK+JEeU8Cod+59TURvnAKUJqFAPwJ3w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: OS0PR01MB5826 Subject: [ovs-dev] [PATCH v4 1/1] ofproto-dpif-trace: Improve conjunctive match tracing. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" A conjunctive flow consists of two or more multiple flows with conjunction actions. When input to the ofproto/trace command matches a conjunctive flow, it outputs flows of all dimensions. Signed-off-by: Nobuhiro MIKI Acked-by: Simon Horman --- v4: * Fix conj_id matching * Fix priority matching * Add a new test v3: * Remove struct flow changes. * Use struct 'cls_rule' instead of struct 'flow'. * Add priority and id conditionals for 'soft' arrays. * Use 'minimask' in struct 'cls_rule' as mask. * Use hmapx instead of ovs_list to store conj flows. * Passe 'conj_flows' as an argument only when tracing. v2: * Reimplemented v1 with a safer and cleaner approach, since v1 was a messy implementation that rewrote const variables. --- lib/classifier.c | 51 +++++++++++++++++++++++++++++++----- lib/classifier.h | 4 ++- lib/ovs-router.c | 5 ++-- lib/tnl-ports.c | 6 ++--- ofproto/ofproto-dpif-xlate.c | 34 ++++++++++++++++++++++-- ofproto/ofproto-dpif-xlate.h | 3 +++ ofproto/ofproto-dpif.c | 25 +++++++++++++----- ofproto/ofproto-dpif.h | 3 ++- tests/classifier.at | 29 ++++++++++++++++++++ tests/test-classifier.c | 8 +++--- 10 files changed, 142 insertions(+), 26 deletions(-) diff --git a/lib/classifier.c b/lib/classifier.c index 18dbfc83ad44..8fd056f2d283 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -853,6 +853,32 @@ trie_ctx_init(struct trie_ctx *ctx, const struct cls_trie *trie) ctx->lookup_done = false; } +static void +insert_conj_flows(struct hmapx *conj_flows, uint32_t id, int priority, + struct cls_conjunction_set **soft, size_t n_soft) +{ + struct cls_conjunction_set *conj_set; + + if (!conj_flows) { + return; + } + + for (size_t i = 0; i < n_soft; i++) { + conj_set = soft[i]; + + if (conj_set->priority != priority) { + continue; + } + + for (size_t j = 0; j < conj_set->n; j++) { + if (conj_set->conj[j].id == id) { + hmapx_add(conj_flows, (void *) (conj_set->match->cls_rule)); + break; + } + } + } +} + struct conjunctive_match { struct hmap_node hmap_node; uint32_t id; @@ -933,11 +959,15 @@ free_conjunctive_matches(struct hmap *matches, * recursion within this function itself. * * 'flow' is non-const to allow for temporary modifications during the lookup. - * Any changes are restored before returning. */ + * Any changes are restored before returning. + * + * 'conj_flows' is an optional parameter. If it is non-null, the matching + * conjunctive flows are inserted. */ static const struct cls_rule * classifier_lookup__(const struct classifier *cls, ovs_version_t version, struct flow *flow, struct flow_wildcards *wc, - bool allow_conjunctive_matches) + bool allow_conjunctive_matches, + struct hmapx *conj_flows) { struct trie_ctx trie_ctx[CLS_MAX_TRIES]; const struct cls_match *match; @@ -1097,10 +1127,15 @@ classifier_lookup__(const struct classifier *cls, ovs_version_t version, const struct cls_rule *rule; flow->conj_id = id; - rule = classifier_lookup__(cls, version, flow, wc, false); + rule = classifier_lookup__(cls, version, flow, wc, false, + NULL); flow->conj_id = saved_conj_id; if (rule) { + if (allow_conjunctive_matches) { + insert_conj_flows(conj_flows, id, soft_pri, soft, + n_soft); + } free_conjunctive_matches(&matches, cm_stubs, ARRAY_SIZE(cm_stubs)); if (soft != soft_stub) { @@ -1161,12 +1196,16 @@ classifier_lookup__(const struct classifier *cls, ovs_version_t version, * flow_wildcards_init_catchall()). * * 'flow' is non-const to allow for temporary modifications during the lookup. - * Any changes are restored before returning. */ + * Any changes are restored before returning. + * + * 'conj_flows' is an optional parameter. If it is non-null, the matching + * conjunctive flows are inserted. */ const struct cls_rule * classifier_lookup(const struct classifier *cls, ovs_version_t version, - struct flow *flow, struct flow_wildcards *wc) + struct flow *flow, struct flow_wildcards *wc, + struct hmapx *conj_flows) { - return classifier_lookup__(cls, version, flow, wc, true); + return classifier_lookup__(cls, version, flow, wc, true, conj_flows); } /* Finds and returns a rule in 'cls' with exactly the same priority and diff --git a/lib/classifier.h b/lib/classifier.h index f646a8f7429b..f55a2cba998e 100644 --- a/lib/classifier.h +++ b/lib/classifier.h @@ -299,6 +299,7 @@ * parallel to the rule's removal. */ #include "cmap.h" +#include "hmapx.h" #include "openvswitch/match.h" #include "openvswitch/meta-flow.h" #include "pvector.h" @@ -398,7 +399,8 @@ static inline void classifier_publish(struct classifier *); * and each other. */ const struct cls_rule *classifier_lookup(const struct classifier *, ovs_version_t, struct flow *, - struct flow_wildcards *); + struct flow_wildcards *, + struct hmapx *conj_flows); bool classifier_rule_overlaps(const struct classifier *, const struct cls_rule *, ovs_version_t); const struct cls_rule *classifier_find_rule_exactly(const struct classifier *, diff --git a/lib/ovs-router.c b/lib/ovs-router.c index 7c04bb0e6b14..ca014d80ed31 100644 --- a/lib/ovs-router.c +++ b/lib/ovs-router.c @@ -115,7 +115,8 @@ ovs_router_lookup(uint32_t mark, const struct in6_addr *ip6_dst, const struct cls_rule *cr_src; struct flow flow_src = {.ipv6_dst = *src, .pkt_mark = mark}; - cr_src = classifier_lookup(&cls, OVS_VERSION_MAX, &flow_src, NULL); + cr_src = classifier_lookup(&cls, OVS_VERSION_MAX, &flow_src, NULL, + NULL); if (cr_src) { struct ovs_router_entry *p_src = ovs_router_entry_cast(cr_src); if (!p_src->local) { @@ -126,7 +127,7 @@ ovs_router_lookup(uint32_t mark, const struct in6_addr *ip6_dst, } } - cr = classifier_lookup(&cls, OVS_VERSION_MAX, &flow, NULL); + cr = classifier_lookup(&cls, OVS_VERSION_MAX, &flow, NULL, NULL); if (cr) { struct ovs_router_entry *p = ovs_router_entry_cast(cr); diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c index f16409a0bf08..bb0b0b0c55f4 100644 --- a/lib/tnl-ports.c +++ b/lib/tnl-ports.c @@ -112,7 +112,7 @@ map_insert(odp_port_t port, struct eth_addr mac, struct in6_addr *addr, tnl_port_init_flow(&match.flow, mac, addr, nw_proto, tp_port); do { - cr = classifier_lookup(&cls, OVS_VERSION_MAX, &match.flow, NULL); + cr = classifier_lookup(&cls, OVS_VERSION_MAX, &match.flow, NULL, NULL); p = tnl_port_cast(cr); /* Try again if the rule was released before we get the reference. */ } while (p && !ovs_refcount_try_ref_rcu(&p->ref_cnt)); @@ -247,7 +247,7 @@ map_delete(struct eth_addr mac, struct in6_addr *addr, tnl_port_init_flow(&flow, mac, addr, nw_proto, tp_port); - cr = classifier_lookup(&cls, OVS_VERSION_MAX, &flow, NULL); + cr = classifier_lookup(&cls, OVS_VERSION_MAX, &flow, NULL, NULL); tnl_port_unref(cr); } @@ -305,7 +305,7 @@ odp_port_t tnl_port_map_lookup(struct flow *flow, struct flow_wildcards *wc) { const struct cls_rule *cr = classifier_lookup(&cls, OVS_VERSION_MAX, flow, - wc); + wc, NULL); return (cr) ? tnl_port_cast(cr)->portno : ODPP_NONE; } diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index e243773307b7..bae5d8077b51 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -866,6 +866,28 @@ xlate_report_action_set(const struct xlate_ctx *ctx, const char *verb) } } +static void +xlate_report_conj_matches(const struct xlate_ctx *ctx) +{ + struct hmapx_node *node; + struct cls_rule *rule; + struct match match; + + /* NOTE: The conj flows have meaning in order. But now they + * are put into the hmapx structure, so the order may + * have been rearranged. */ + HMAPX_FOR_EACH (node, &ctx->xout->conj_flows) { + struct ds s = DS_EMPTY_INITIALIZER; + + rule = node->data; + minimatch_expand(&rule->match, &match); + + match_format(&match, NULL, &s, rule->priority); + xlate_report_debug(ctx, OFT_DETAIL, "conj. %s", ds_cstr(&s)); + + ds_destroy(&s); + } +} /* If tracing is enabled in 'ctx', appends a node representing 'rule' (in * OpenFlow table 'table_id') to the trace and makes this node the parent for @@ -918,6 +940,8 @@ xlate_report_table(const struct xlate_ctx *ctx, struct rule_dpif *rule, ctx->xin->trace = &oftrace_report(ctx->xin->trace, OFT_TABLE, ds_cstr(&s))->subs; ds_destroy(&s); + + xlate_report_conj_matches(ctx); } /* If tracing is enabled in 'ctx', adds an OFT_DETAIL trace node to 'ctx' @@ -4653,7 +4677,8 @@ xlate_table_action(struct xlate_ctx *ctx, ofp_port_t in_port, uint8_t table_id, ctx->xin->resubmit_stats, &ctx->table_id, in_port, may_packet_in, honor_table_miss, - ctx->xin->xcache); + ctx->xin->xcache, + &ctx->xout->conj_flows); /* Swap back. */ if (with_ct_orig) { tuple_swap(&ctx->xin->flow, ctx->wc); @@ -7970,6 +7995,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) *xout = (struct xlate_out) { .slow = 0, .recircs = RECIRC_REFS_EMPTY_INITIALIZER, + .conj_flows = HMAPX_INITIALIZER(&xout->conj_flows), }; struct xlate_cfg *xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp); @@ -8181,7 +8207,8 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) ctx.rule = rule_dpif_lookup_from_table( ctx.xbridge->ofproto, ctx.xin->tables_version, flow, ctx.wc, ctx.xin->resubmit_stats, &ctx.table_id, - flow->in_port.ofp_port, true, true, ctx.xin->xcache); + flow->in_port.ofp_port, true, true, ctx.xin->xcache, + ctx.xin->trace ? &ctx.xout->conj_flows : NULL); if (ctx.xin->resubmit_stats) { rule_dpif_credit_stats(ctx.rule, ctx.xin->resubmit_stats, false); } @@ -8375,6 +8402,9 @@ exit: ofpbuf_uninit(&scratch_actions); ofpbuf_delete(ctx.encap_data); + /* Clean up 'conj_flows' as it is no longer needed. */ + hmapx_destroy(&xout->conj_flows); + /* Make sure we return a "drop flow" in case of an error. */ if (ctx.error) { xout->slow = 0; diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index 05b46fb26b1c..3d549239dfea 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -61,6 +61,9 @@ struct xlate_out { /* Recirc action IDs on which references are held. */ struct recirc_refs recircs; + + /* Set of matching conjunctive flows. */ + struct hmapx conj_flows; }; struct xlate_in { diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index ba5706f6adcc..8cc0a6506534 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -4383,15 +4383,20 @@ ofproto_dpif_get_tables_version(struct ofproto_dpif *ofproto) * a reference. * * 'flow' is non-const to allow for temporary modifications during the lookup. - * Any changes are restored before returning. */ + * Any changes are restored before returning. + * + * 'conj_flows' is an optional parameter. If it is non-null, the matching + * conjunctive flows are inserted. */ static struct rule_dpif * rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, ovs_version_t version, uint8_t table_id, struct flow *flow, - struct flow_wildcards *wc) + struct flow_wildcards *wc, + struct hmapx *conj_flows) { struct classifier *cls = &ofproto->up.tables[table_id].cls; return rule_dpif_cast(rule_from_cls_rule(classifier_lookup(cls, version, - flow, wc))); + flow, wc, + conj_flows))); } void @@ -4433,7 +4438,10 @@ ofproto_dpif_credit_table_stats(struct ofproto_dpif *ofproto, uint8_t table_id, * 'in_port'. This is needed for resubmit action support. * * 'flow' is non-const to allow for temporary modifications during the lookup. - * Any changes are restored before returning. */ + * Any changes are restored before returning. + * + * 'conj_flows' is an optional parameter. If it is non-null, the matching + * conjunctive flows are inserted. */ struct rule_dpif * rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, ovs_version_t version, struct flow *flow, @@ -4441,7 +4449,8 @@ rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, const struct dpif_flow_stats *stats, uint8_t *table_id, ofp_port_t in_port, bool may_packet_in, bool honor_table_miss, - struct xlate_cache *xcache) + struct xlate_cache *xcache, + struct hmapx *conj_flows) { ovs_be16 old_tp_src = flow->tp_src, old_tp_dst = flow->tp_dst; ofp_port_t old_in_port = flow->in_port.ofp_port; @@ -4497,7 +4506,8 @@ rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, next_id++, next_id += (next_id == TBL_INTERNAL)) { *table_id = next_id; - rule = rule_dpif_lookup_in_table(ofproto, version, next_id, flow, wc); + rule = rule_dpif_lookup_in_table(ofproto, version, next_id, flow, wc, + conj_flows); if (stats) { struct oftable *tbl = &ofproto->up.tables[next_id]; unsigned long orig; @@ -6680,7 +6690,8 @@ ofproto_dpif_add_internal_flow(struct ofproto_dpif *ofproto, rule = rule_dpif_lookup_in_table(ofproto, ofproto_dpif_get_tables_version(ofproto), - TBL_INTERNAL, &match->flow, &match->wc); + TBL_INTERNAL, &match->flow, &match->wc, + NULL); if (rule) { *rulep = &rule->up; } else { diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index d8e0cd37ac5b..1fe22ab41bd9 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -103,7 +103,8 @@ struct rule_dpif *rule_dpif_lookup_from_table(struct ofproto_dpif *, ofp_port_t in_port, bool may_packet_in, bool honor_table_miss, - struct xlate_cache *); + struct xlate_cache *, + struct hmapx *conj_flows); void rule_dpif_credit_stats(struct rule_dpif *, const struct dpif_flow_stats *, bool); diff --git a/tests/classifier.at b/tests/classifier.at index de2705653e00..257a495985da 100644 --- a/tests/classifier.at +++ b/tests/classifier.at @@ -276,6 +276,13 @@ for src in 0 1 2 3 4 5 6 7; do AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=1,dl_type=0x0800,nw_src=10.0.0.$src,nw_dst=10.0.0.$dst"], [0], [stdout]) AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: $out ]) + dnl Check detailed output for conjunctive match. + if test $out = 3; then + AT_CHECK_UNQUOTED([cat stdout | grep conj\\. | sort], [0], [dnl + -> conj. priority=100,ip,nw_dst=10.0.0.$dst + -> conj. priority=100,ip,nw_src=10.0.0.$src +]) + fi done done OVS_VSWITCHD_STOP @@ -418,6 +425,28 @@ ovs-ofctl: "conjunction" actions may be used along with "note" but not any other OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([conjunctive match with same priority]) +OVS_VSWITCHD_START +add_of_ports br0 1 2 +AT_DATA([flows.txt], [dnl +conj_id=1,actions=2 +conj_id=2,actions=drop + +priority=10,ip,ip_dst=10.0.0.1,actions=conjunction(1,1/2) +priority=10,ip,ip_src=10.0.0.2,actions=conjunction(1,2/2) +priority=10,ip,ip_dst=10.0.0.3,actions=conjunction(2,1/2) +priority=10,ip,in_port=1,actions=conjunction(2,2/2) +]) +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) +# Check that "priority=10,ip,in_port=1,actions=conjunction(2,2/2)" is +# correctly excluded from the output. +AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=1,dl_type=0x0800,nw_dst=10.0.0.1,nw_src=10.0.0.2" | grep conj\\. | sort], [0], [dnl + -> conj. priority=10,ip,nw_dst=10.0.0.1 + -> conj. priority=10,ip,nw_src=10.0.0.2 +]) +OVS_VSWITCHD_STOP +AT_CLEANUP + # Flow classifier a packet with excess of padding. AT_SETUP([flow classifier - packet with extra padding]) OVS_VSWITCHD_START diff --git a/tests/test-classifier.c b/tests/test-classifier.c index cff00c8fa35e..2c1604a01e2e 100644 --- a/tests/test-classifier.c +++ b/tests/test-classifier.c @@ -441,7 +441,7 @@ compare_classifiers(struct classifier *cls, size_t n_invisible_rules, /* This assertion is here to suppress a GCC 4.9 array-bounds warning */ ovs_assert(cls->n_tries <= CLS_MAX_TRIES); - cr0 = classifier_lookup(cls, version, &flow, &wc); + cr0 = classifier_lookup(cls, version, &flow, &wc, NULL); cr1 = tcls_lookup(tcls, &flow); assert((cr0 == NULL) == (cr1 == NULL)); if (cr0 != NULL) { @@ -454,7 +454,7 @@ compare_classifiers(struct classifier *cls, size_t n_invisible_rules, /* Make sure the rule should have been visible. */ assert(cls_rule_visible_in_version(cr0, version)); } - cr2 = classifier_lookup(cls, version, &flow, NULL); + cr2 = classifier_lookup(cls, version, &flow, NULL, NULL); assert(cr2 == cr0); } } @@ -1370,10 +1370,10 @@ lookup_classifier(void *aux_) if (aux->use_wc) { flow_wildcards_init_catchall(&wc); cr = classifier_lookup(aux->cls, version, &aux->lookup_flows[x], - &wc); + &wc, NULL); } else { cr = classifier_lookup(aux->cls, version, &aux->lookup_flows[x], - NULL); + NULL, NULL); } if (cr) { hits++;