From patchwork Tue Nov 22 14:03:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 24396 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2219636wrr; Tue, 22 Nov 2022 06:10:14 -0800 (PST) X-Google-Smtp-Source: AA0mqf7Lk1/2OgsByI22/jqQXCWS9Tpft7hhE1g+2IF2hh60UikjJINDp5gCDqwEKinsFQTPLW2g X-Received: by 2002:aa7:9af5:0:b0:56c:b5fc:9167 with SMTP id y21-20020aa79af5000000b0056cb5fc9167mr5674151pfp.40.1669126213892; Tue, 22 Nov 2022 06:10:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669126213; cv=none; d=google.com; s=arc-20160816; b=HTWeFGyfMRxUnT8fpmgvxziTY0coBojLnMIA+spXNXap20Z88mUGnzvkoq6J8RFLTv fqXfBZrl8ctQOuv2We6f1GWefdStQ2zp5hxOKsCC2ZxhImq4wSi56QmKIWfBIZxbXSXW biryIDWsWxgBUHRw8IDZ3uQ+LokGB0+x1QncGpjE76G8k0uo6/mhT8alaCTbtJbtFFTF /J2lZqWqKiHqavDzvRcs3r5VhTmzJDrX0nNODFufr63QJtXYKr3r2BOIsx6lH1uMUFbe GZ6XsyIYdLXQ1bIwiYHphbbLoj2VCY8HlUp1hEANgZrqFYmT6/gFEv7n8M0EmttdlDT9 yC+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=Dwl7SbsKJoZEUQcBj1alw3gjGL8Zf4MEaXU4djfJOx0=; b=guMTNCKR4MEgR+fMRpGegBKlp1qZya8JhBnSIdplMmMYxxGq6kV4eInip9UEV3cPRQ aXcG0BnP0EbDmr01QPZvMVHx9ojKZiOVDgaj9IJSRwTxnakuPNa5jCsxggegPYY331ny YXS6ZDXoF+VZHHR7NPCdyUEE7l8LUNFDluUCxt6vAPulOLR/EIF2FFzweituDHfseaCK s3UNMLcexShdOp6AJueUCaC2N9ZD3tX2qr/ZNcoqxo8p9AN1MxaR3NJ4DyC0jfF9Uhql uoQflgO3lLR+zaqWDZ9mH56AEdg1fIwfcl/m0Nxhg+Splk1rkKrULRgNTqO5bKDsyY7c fTJw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Vqamq8Di; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id 4-20020a17090a1a4400b00218c0f831bbsi3735398pjl.111.2022.11.22.06.09.52; Tue, 22 Nov 2022 06:10:13 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Vqamq8Di; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233960AbiKVOEW (ORCPT + 99 others); Tue, 22 Nov 2022 09:04:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55554 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233008AbiKVOEM (ORCPT ); Tue, 22 Nov 2022 09:04:12 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E3A81D65D for ; Tue, 22 Nov 2022 06:03:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669125793; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Dwl7SbsKJoZEUQcBj1alw3gjGL8Zf4MEaXU4djfJOx0=; b=Vqamq8DiIVFobKw9hz46nUstpRCZu7uI+d778HL9fhI6xMAakieFvtRGu7Bn8qXWt/jgTg PbtmLsTjW93ra9kTNOX7a97EwnuQ7lFu1873rtn+IeZagME4BsxxsHrJy3wpU8ZZAocrW+ wQ7rdMzMiDXowKIupmlSz5tM/BcY1qY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-265-Pe1qYOMCPw-rHDPPfBq8NA-1; Tue, 22 Nov 2022 09:03:11 -0500 X-MC-Unique: Pe1qYOMCPw-rHDPPfBq8NA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A8A38811E75; Tue, 22 Nov 2022 14:03:10 +0000 (UTC) Received: from RHTPC1VM0NT.redhat.com (unknown [10.22.16.203]) by smtp.corp.redhat.com (Postfix) with ESMTP id 33BDC40C6EC6; Tue, 22 Nov 2022 14:03:10 +0000 (UTC) From: Aaron Conole To: netdev@vger.kernel.org Cc: Pravin B Shelar , Jakub Kicinski , "David S. Miller" , Paolo Abeni , Eric Dumazet , Thomas Graf , dev@openvswitch.org, Eelco Chaudron , Ilya Maximets , Shuah Khan , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [RFC net-next 1/6] openvswitch: exclude kernel flow key from upcalls Date: Tue, 22 Nov 2022 09:03:02 -0500 Message-Id: <20221122140307.705112-2-aconole@redhat.com> In-Reply-To: <20221122140307.705112-1-aconole@redhat.com> References: <20221122140307.705112-1-aconole@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750205688771162812?= X-GMAIL-MSGID: =?utf-8?q?1750205688771162812?= When processing upcall commands, two groups of data are available to userspace for processing: the actual packet data and the kernel sw flow key data. The inclusion of the flow key allows the userspace avoid running through the dissection again. However, the userspace can choose to ignore the flow key data, as is the case in some ovs-vswitchd upcall processing. For these messages, having the flow key data merely adds additional data to the upcall pipeline without any actual gain. Userspace simply throws the data away anyway. Introduce a new feature OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY which signals that the userspace doesn't want upcalls included with specific class of message (for example MISS messages). The associated attribute OVS_DP_ATTR_EXCLUDE_CMDS tells which specific commands to omit via a bitmask. A test will be added to showcase using the feature. Signed-off-by: Aaron Conole --- include/uapi/linux/openvswitch.h | 6 ++++++ net/openvswitch/datapath.c | 26 ++++++++++++++++++++++---- net/openvswitch/datapath.h | 2 ++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index 94066f87e9ee..238e62ecba46 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h @@ -95,6 +95,9 @@ enum ovs_datapath_attr { * per-cpu dispatch mode */ OVS_DP_ATTR_IFINDEX, + OVS_DP_ATTR_EXCLUDE_CMDS, /* u32 mask of OVS_PACKET_CMDs for + * omitting FLOW_KEY attribute + */ __OVS_DP_ATTR_MAX }; @@ -138,6 +141,9 @@ struct ovs_vport_stats { /* Allow per-cpu dispatch of upcalls */ #define OVS_DP_F_DISPATCH_UPCALL_PER_CPU (1 << 3) +/* Drop Flow key data from upcall packet cmds */ +#define OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY (1 << 4) + /* Fixed logical ports. */ #define OVSP_LOCAL ((__u32)0) diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 861dfb8daf4a..6afde7de492c 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -470,9 +470,13 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, } upcall->dp_ifindex = dp_ifindex; - err = ovs_nla_put_key(key, key, OVS_PACKET_ATTR_KEY, false, user_skb); - if (err) - goto out; + if (!(dp->user_features & OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY) || + !(dp->upcall_exclude_cmds & (1U << upcall_info->cmd))) { + err = ovs_nla_put_key(key, key, OVS_PACKET_ATTR_KEY, false, + user_skb); + if (err) + goto out; + } if (upcall_info->userdata) __nla_put(user_skb, OVS_PACKET_ATTR_USERDATA, @@ -1526,6 +1530,7 @@ static size_t ovs_dp_cmd_msg_size(void) msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */ msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_MASKS_CACHE_SIZE */ msgsize += nla_total_size(sizeof(u32) * nr_cpu_ids); /* OVS_DP_ATTR_PER_CPU_PIDS */ + msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_EXCLUDE_CMDS */ return msgsize; } @@ -1574,6 +1579,10 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, goto nla_put_failure; } + if (nla_put_u32(skb, OVS_DP_ATTR_EXCLUDE_CMDS, + dp->upcall_exclude_cmds)) + goto nla_put_failure; + genlmsg_end(skb, ovs_header); return 0; @@ -1684,7 +1693,8 @@ static int ovs_dp_change(struct datapath *dp, struct nlattr *a[]) if (user_features & ~(OVS_DP_F_VPORT_PIDS | OVS_DP_F_UNALIGNED | OVS_DP_F_TC_RECIRC_SHARING | - OVS_DP_F_DISPATCH_UPCALL_PER_CPU)) + OVS_DP_F_DISPATCH_UPCALL_PER_CPU | + OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY)) return -EOPNOTSUPP; #if !IS_ENABLED(CONFIG_NET_TC_SKB_EXT) @@ -1705,6 +1715,14 @@ static int ovs_dp_change(struct datapath *dp, struct nlattr *a[]) dp->user_features = user_features; + if (dp->user_features & OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY) { + if (!a[OVS_DP_ATTR_EXCLUDE_CMDS]) + return -EINVAL; + + dp->upcall_exclude_cmds = + nla_get_u32(a[OVS_DP_ATTR_EXCLUDE_CMDS]); + } + if (dp->user_features & OVS_DP_F_DISPATCH_UPCALL_PER_CPU && a[OVS_DP_ATTR_PER_CPU_PIDS]) { /* Upcall Netlink Port IDs have been updated */ diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index 0cd29971a907..3c951e25509e 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h @@ -101,6 +101,8 @@ struct datapath { u32 max_headroom; + u32 upcall_exclude_cmds; + /* Switch meters. */ struct dp_meter_table meter_tbl; From patchwork Tue Nov 22 14:03:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 24397 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2219721wrr; Tue, 22 Nov 2022 06:10:24 -0800 (PST) X-Google-Smtp-Source: AA0mqf7rqtH0v+OHdwqbpbhiJsyGlg7lznfmaWgQsuGKluY4mKpy8BlVsaIgfa0v9kL7b2D0Ngmf X-Received: by 2002:a05:6a00:850:b0:573:a511:d017 with SMTP id q16-20020a056a00085000b00573a511d017mr10249437pfk.39.1669126224243; Tue, 22 Nov 2022 06:10:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669126224; cv=none; d=google.com; s=arc-20160816; b=xbyFLYXRq/Izf4H97Jy0xt/Jb3JLjVfyuiXZ1uGjrd1R/wAYnVuI3kGGPoQFXupHZ7 yEvXTxBSUfPBJL0eM2stdyZkswlLZ9Z3p8OjqtAx59qD7DCUGuo9uYF8tSHkqhPbQHhc pnxEID1HIw4SmNuui3GcZK2BtfHmLnZrm9DaJmU2m42a7qGz4IRUM5GtTttxkIXvYjqN i0nLckNJFR4+hrsSn5BKdH0vDMFi9zqTVQKlQa7WINPnGm9XhR+Rn4wBsPH+UsCsiX24 +GIK+T9sKl4pxH4WvaP79Tqo/XSDUIyfhAWxS97VCgg4k6TJuW+AbgXiP/SVpmYzzqYZ AdPw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=QNoI4qCUFYL/xV13yMWx+XxtSlVza2fkeLu+mGHpsuU=; b=du7B/ePtvW/XBScuDNXBr/Vzv2Q509KQRzml6Q5nyYKNDqG+cMR6Jn86Mm2sLDdQFf DFj60zF3GVaSi3MoPFJB/Nt8MW4vyEgdJgafk2CPsf9IEjhfvfIUaYGk6+jt14qtXPLH us3u0ljd4UaTYlbigrpKyu1dKHHqtuSIB5qsVoTZfVhsWGhA1vRuybAesDWms96y3AXW mud3X2HFUMieUylCeJin5plafVoI0imRX55AkFE9xb8a4iLK8QpEAWNC/J2LM7lrRTm7 8FOaDvdtiNTmaw3auGUg/gz4UACEGw8Ayv+0WtCc+P7tPNyxMGZ0So9MWqR9f5lpY83X 6+MA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ckBkrin0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id z184-20020a6333c1000000b004773bf41b74si10609923pgz.30.2022.11.22.06.10.03; Tue, 22 Nov 2022 06:10:24 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ckBkrin0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233956AbiKVOES (ORCPT + 99 others); Tue, 22 Nov 2022 09:04:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55598 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232875AbiKVOEM (ORCPT ); Tue, 22 Nov 2022 09:04:12 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 275FD1DA62 for ; Tue, 22 Nov 2022 06:03:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669125795; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QNoI4qCUFYL/xV13yMWx+XxtSlVza2fkeLu+mGHpsuU=; b=ckBkrin0CLVsg11H0+GI9hdPXo+kJIrcbuGqcSbE8KNwi5bxMFoahBAb63L0/mwLvY2sU1 oHhuDfgE7CVKl5jy3N4kXgz22k22gcYOl3bWrsQ7e2aVvSmeATnBQfwv1X033HBm6agYg+ 7aG2itiZMm/00sN098GW1VgUtEcqiv0= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-653-naWpKHZOMUKlEWZ2T80u0g-1; Tue, 22 Nov 2022 09:03:12 -0500 X-MC-Unique: naWpKHZOMUKlEWZ2T80u0g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3D9E51C08790; Tue, 22 Nov 2022 14:03:11 +0000 (UTC) Received: from RHTPC1VM0NT.redhat.com (unknown [10.22.16.203]) by smtp.corp.redhat.com (Postfix) with ESMTP id B92A540C6EC6; Tue, 22 Nov 2022 14:03:10 +0000 (UTC) From: Aaron Conole To: netdev@vger.kernel.org Cc: Pravin B Shelar , Jakub Kicinski , "David S. Miller" , Paolo Abeni , Eric Dumazet , Thomas Graf , dev@openvswitch.org, Eelco Chaudron , Ilya Maximets , Shuah Khan , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [RFC net-next 2/6] selftests: openvswitch: add interface support Date: Tue, 22 Nov 2022 09:03:03 -0500 Message-Id: <20221122140307.705112-3-aconole@redhat.com> In-Reply-To: <20221122140307.705112-1-aconole@redhat.com> References: <20221122140307.705112-1-aconole@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750205699581408989?= X-GMAIL-MSGID: =?utf-8?q?1750205699581408989?= Includes an associated test to generate netns and connect interfaces, with the option to include tcp tracing. This will be used in the future when flow support is added for additional test cases. Signed-off-by: Aaron Conole --- .../selftests/net/openvswitch/openvswitch.sh | 54 ++++++++ .../selftests/net/openvswitch/ovs-dpctl.py | 120 ++++++++++++++++-- 2 files changed, 165 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh index 7ce46700a3ae..ce14913150fe 100755 --- a/tools/testing/selftests/net/openvswitch/openvswitch.sh +++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh @@ -70,6 +70,49 @@ ovs_add_dp () { on_exit "ovs_sbx $sbxname python3 $ovs_base/ovs-dpctl.py del-dp $1;" } +ovs_add_if () { + info "Adding IF to DP: br:$2 if:$3" + ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-if "$2" "$3" || return 1 +} + +ovs_del_if () { + info "Deleting IF from DP: br:$2 if:$3" + ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py del-if "$2" "$3" || return 1 +} + +ovs_netns_spawn_daemon() { + sbx=$1 + shift + netns=$1 + shift + info "spawning cmd: $*" + ip netns exec $netns $* >> $ovs_dir/stdout 2>> $ovs_dir/stderr & + pid=$! + ovs_sbx "$sbx" on_exit "kill -TERM $pid 2>/dev/null" +} + +ovs_add_netns_and_veths () { + info "Adding netns attached: sbx:$1 dp:$2 {$3, $4, $5}" + + ovs_sbx "$1" ip netns add "$3" || return 1 + on_exit "ovs_sbx $1 ip netns del $3" + ovs_sbx "$1" ip link add "$4" type veth peer name "$5" || return 1 + on_exit "ovs_sbx $1 ip link del $4 >/dev/null 2>&1" + ovs_sbx "$1" ip link set "$4" up || return 1 + ovs_sbx "$1" ip link set "$5" netns "$3" || return 1 + ovs_sbx "$1" ip netns exec "$3" ip link set "$5" up || return 1 + + if [ "$6" != "" ]; then + ovs_sbx "$1" ip netns exec "$4" ip addr add "$6" dev "$5" \ + || return 1 + fi + ovs_add_if "$1" "$2" "$4" || return 1 + [ $TRACING -eq 1 ] && ovs_netns_spawn_daemon "$1" "$3" \ + tcpdump -i any -s 65535 >> ${ovs_dir}/tcpdump_"$3".log + + return 0 +} + usage() { echo echo "$0 [OPTIONS] [TEST]..." @@ -101,6 +144,17 @@ test_netlink_checks () { return 1 fi + ovs_add_netns_and_veths "test_netlink_checks" nv0 left left0 l0 || \ + return 1 + ovs_add_netns_and_veths "test_netlink_checks" nv0 right right0 r0 || \ + return 1 + [ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \ + wc -l) == 3 ] || \ + return 1 + ovs_del_if "test_netlink_checks" nv0 right0 || return 1 + [ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \ + wc -l) == 2 ] || \ + return 1 return 0 } diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py index 3243c90d449e..338e9b2cd660 100644 --- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py +++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py @@ -170,6 +170,13 @@ class OvsDatapath(GenericNetlinkSocket): class OvsVport(GenericNetlinkSocket): + + OVS_VPORT_TYPE_NETDEV = 1 + OVS_VPORT_TYPE_INTERNAL = 2 + OVS_VPORT_TYPE_GRE = 3 + OVS_VPORT_TYPE_VXLAN = 4 + OVS_VPORT_TYPE_GENEVE = 5 + class ovs_vport_msg(ovs_dp_msg): nla_map = ( ("OVS_VPORT_ATTR_UNSPEC", "none"), @@ -197,17 +204,30 @@ class OvsVport(GenericNetlinkSocket): ) def type_to_str(vport_type): - if vport_type == 1: + if vport_type == OvsVport.OVS_VPORT_TYPE_NETDEV: return "netdev" - elif vport_type == 2: + elif vport_type == OvsVport.OVS_VPORT_TYPE_INTERNAL: return "internal" - elif vport_type == 3: + elif vport_type == OvsVport.OVS_VPORT_TYPE_GRE: return "gre" - elif vport_type == 4: + elif vport_type == OvsVport.OVS_VPORT_TYPE_VXLAN: return "vxlan" - elif vport_type == 5: + elif vport_type == OvsVport.OVS_VPORT_TYPE_GENEVE: return "geneve" - return "unknown:%d" % vport_type + raise ValueError("Unknown vport type:%d" % vport_type) + + def str_to_type(vport_type): + if vport_type == "netdev": + return OvsVport.OVS_VPORT_TYPE_NETDEV + elif vport_type == "internal": + return OvsVport.OVS_VPORT_TYPE_INTERNAL + elif vport_type == "gre": + return OvsVport.OVS_VPORT_TYPE_INTERNAL + elif vport_type == "vxlan": + return OvsVport.OVS_VPORT_TYPE_VXLAN + elif vport_type == "geneve": + return OvsVport.OVS_VPORT_TYPE_GENEVE + raise ValueError("Unknown vport type: '%s'" % vport_type) def __init__(self): GenericNetlinkSocket.__init__(self) @@ -238,8 +258,51 @@ class OvsVport(GenericNetlinkSocket): raise ne return reply + def attach(self, dpindex, vport_ifname, ptype): + msg = OvsVport.ovs_vport_msg() + + msg["cmd"] = OVS_VPORT_CMD_NEW + msg["version"] = OVS_DATAPATH_VERSION + msg["reserved"] = 0 + msg["dpifindex"] = dpindex + port_type = OvsVport.str_to_type(ptype) + + msg["attrs"].append(["OVS_VPORT_ATTR_TYPE", port_type]) + msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) + msg["attrs"].append(["OVS_VPORT_ATTR_UPCALL_PID", [self.pid]]) + + try: + reply = self.nlm_request( + msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK + ) + reply = reply[0] + except NetlinkError as ne: + raise ne + return reply + + def detach(self, dpindex, vport_ifname): + msg = OvsVport.ovs_vport_msg() + + msg["cmd"] = OVS_VPORT_CMD_DEL + msg["version"] = OVS_DATAPATH_VERSION + msg["reserved"] = 0 + msg["dpifindex"] = dpindex + msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) -def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB()): + try: + reply = self.nlm_request( + msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK + ) + reply = reply[0] + except NetlinkError as ne: + if ne.code == errno.ENODEV: + reply = None + else: + raise ne + return reply + + +def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB(), vpl=OvsVport()): dp_name = dp_lookup_rep.get_attr("OVS_DP_ATTR_NAME") base_stats = dp_lookup_rep.get_attr("OVS_DP_ATTR_STATS") megaflow_stats = dp_lookup_rep.get_attr("OVS_DP_ATTR_MEGAFLOW_STATS") @@ -265,7 +328,6 @@ def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB()): print(" features: 0x%X" % user_features) # port print out - vpl = OvsVport() for iface in ndb.interfaces: rep = vpl.info(iface.ifname, ifindex) if rep is not None: @@ -312,9 +374,25 @@ def main(argv): deldpcmd = subparsers.add_parser("del-dp") deldpcmd.add_argument("deldp", help="Datapath Name") + addifcmd = subparsers.add_parser("add-if") + addifcmd.add_argument("dpname", help="Datapath Name") + addifcmd.add_argument("addif", help="Interface name for adding") + addifcmd.add_argument( + "-t", + "--ptype", + type=str, + default="netdev", + choices=["netdev", "internal"], + help="Interface type (default netdev)", + ) + delifcmd = subparsers.add_parser("del-if") + delifcmd.add_argument("dpname", help="Datapath Name") + delifcmd.add_argument("delif", help="Interface name for adding") + args = parser.parse_args() ovsdp = OvsDatapath() + ovsvp = OvsVport() ndb = NDB() if hasattr(args, "showdp"): @@ -328,7 +406,7 @@ def main(argv): if rep is not None: found = True - print_ovsdp_full(rep, iface.index, ndb) + print_ovsdp_full(rep, iface.index, ndb, ovsvp) if not found: msg = "No DP found" @@ -343,6 +421,30 @@ def main(argv): print("DP '%s' added" % args.adddp) elif hasattr(args, "deldp"): ovsdp.destroy(args.deldp) + elif hasattr(args, "addif"): + rep = ovsdp.info(args.dpname, 0) + if rep is None: + print("DP '%s' not found." % args.dpname) + return 1 + rep = ovsvp.attach(rep["dpifindex"], args.addif, args.ptype) + msg = "vport '%s'" % args.addif + if rep and rep["error"] == 0: + msg += " added." + else: + msg += " failed to add." + print(msg) + elif hasattr(args, "delif"): + rep = ovsdp.info(args.dpname, 0) + if rep is None: + print("DP '%s' not found." % args.dpname) + return 1 + rep = ovsvp.detach(rep["dpifindex"], args.delif) + msg = "vport '%s'" % args.delif + if rep and rep["error"] == 0: + msg += " removed." + else: + msg += " failed to remove." + print(msg) return 0 From patchwork Tue Nov 22 14:03:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 24394 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2219452wrr; Tue, 22 Nov 2022 06:09:56 -0800 (PST) X-Google-Smtp-Source: AA0mqf6Gyi8+GnTVpg7EDAm+MF+jN93W3qjMs2ph6kIvtSWqPtiE4f8xecvMt5NcP6ZJlGM9aUnG X-Received: by 2002:a05:6402:2929:b0:469:b603:ca21 with SMTP id ee41-20020a056402292900b00469b603ca21mr5432193edb.350.1669126196348; Tue, 22 Nov 2022 06:09:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669126196; cv=none; d=google.com; s=arc-20160816; b=OB+etNmCpzKBnQm3kddQzOX4IkPKxuJcZzyevxl9TcXWXo8opmGq1zP4Pb3C3GEmgu ilCJ0hLX0He1xM2ilKnNYVypmp68KA6PkZFSEzUaiZiJbozJ/g0OHrBLJS2A0nC2XYhZ sgZM2n17QRAEfj8KEqTnW5XVo8KBukjaVXAqYhuXPwGYT2cAS9nKOj0JoeqjRx/7GuRK GgyKi0FC0dLRG7+wdVnfiDVOozy89NGEMY68zoEND70zVWYLgBnNrE0F23nPA5Ad0b/A nUdw8EV3sFWLzzN/fW1RT5JMrUp3m0MTXTMSpBmNh9qOXfmbIUK0aGsS2y+BIEL2LIHZ R7iQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=UR8kD/9jk6i9BBdJZSKcAvF3HRxWCYSnjKDJt9nFEhM=; b=LwPS1yEGtSERFY9vyxK58ZWFXvQiSL4y7/UqGMwF5HlUbC+xa9a1PC94OQ4ss6FINR yiVhq8rYwdvqhvPnYb46uBv4cguURmx0FCd21mG061UZzaQTsyZc/fX0vS/x9DU8HGXV DXb0n+O5n7sm+LQcrX389Scw58Mw9aYswVJZfq+rxXIEGVZnjyJM73owzpX+mhT8Z9v0 trd+t7KK3vGJBJZ54TiD+aMd0jQ6EiE78Zt83yfvLTk4CBh5XicozUVJJJXx7BZNQbRD cSJRiYSDXDMKJkGzdbuBv5Xp1HPXm/P3/8dz9eIwolhi3dkWi9xHSSLqJcDEE7AyUrWI dgQA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=LDxHirSi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id du8-20020a17090772c800b007919388d2c6si8690117ejc.357.2022.11.22.06.09.23; Tue, 22 Nov 2022 06:09:56 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=LDxHirSi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232565AbiKVOFf (ORCPT + 99 others); Tue, 22 Nov 2022 09:05:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55772 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233982AbiKVOFO (ORCPT ); Tue, 22 Nov 2022 09:05:14 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 016C41EEF2 for ; Tue, 22 Nov 2022 06:03:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669125796; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UR8kD/9jk6i9BBdJZSKcAvF3HRxWCYSnjKDJt9nFEhM=; b=LDxHirSimWpjlqjvfMWM66h7BfQIKUE1WoKzseVsMcXyr6BlWm+Hvbx4p9BFa6WbCaErlJ WyC0EhdFrgUmibRCtuM7dTuQVpQWCZmQAsV4+T8QWjoBiB5nVwmzSD7dW4csa/iDaYXVg6 sCZsQsTC83dvP/PWcYUiR5g03ezAU+U= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-661-kP4iDNrlNKaPfpOSBUHTWA-1; Tue, 22 Nov 2022 09:03:12 -0500 X-MC-Unique: kP4iDNrlNKaPfpOSBUHTWA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CD89038123AE; Tue, 22 Nov 2022 14:03:11 +0000 (UTC) Received: from RHTPC1VM0NT.redhat.com (unknown [10.22.16.203]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4E3EF40C6EC6; Tue, 22 Nov 2022 14:03:11 +0000 (UTC) From: Aaron Conole To: netdev@vger.kernel.org Cc: Pravin B Shelar , Jakub Kicinski , "David S. Miller" , Paolo Abeni , Eric Dumazet , Thomas Graf , dev@openvswitch.org, Eelco Chaudron , Ilya Maximets , Shuah Khan , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [RFC net-next 3/6] selftests: openvswitch: add flow dump support Date: Tue, 22 Nov 2022 09:03:04 -0500 Message-Id: <20221122140307.705112-4-aconole@redhat.com> In-Reply-To: <20221122140307.705112-1-aconole@redhat.com> References: <20221122140307.705112-1-aconole@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750205670707307272?= X-GMAIL-MSGID: =?utf-8?q?1750205670707307272?= Add a basic set of fields to print in a 'dpflow' format. This will be used by future commits to check for flow fields after parsing, as well as verifying the flow fields pushed into the kernel from userspace. Signed-off-by: Aaron Conole --- .../selftests/net/openvswitch/ovs-dpctl.py | 781 +++++++++++++++++- 1 file changed, 780 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py index 338e9b2cd660..d654fe1fe4e6 100644 --- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py +++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py @@ -6,12 +6,16 @@ import argparse import errno +import ipaddress +import logging import sys +import time try: from pyroute2 import NDB from pyroute2.netlink import NLM_F_ACK + from pyroute2.netlink import NLM_F_DUMP from pyroute2.netlink import NLM_F_REQUEST from pyroute2.netlink import genlmsg from pyroute2.netlink import nla @@ -40,6 +44,11 @@ OVS_VPORT_CMD_DEL = 2 OVS_VPORT_CMD_GET = 3 OVS_VPORT_CMD_SET = 4 +OVS_FLOW_CMD_NEW = 1 +OVS_FLOW_CMD_DEL = 2 +OVS_FLOW_CMD_GET = 3 +OVS_FLOW_CMD_SET = 4 + class ovs_dp_msg(genlmsg): # include the OVS version @@ -302,6 +311,760 @@ class OvsVport(GenericNetlinkSocket): return reply +def macstr(mac): + outstr = ":".join(["%02X" % i for i in mac]) + return outstr + + +class OvsFlow(GenericNetlinkSocket): + class ovs_flow_msg(ovs_dp_msg): + nla_map = ( + ("OVS_FLOW_ATTR_UNSPEC", "none"), + ("OVS_FLOW_ATTR_KEY", "nested"), + ("OVS_FLOW_ATTR_ACTIONS", "nested"), + ("OVS_FLOW_ATTR_STATS", "flowstats"), + ("OVS_FLOW_ATTR_TCP_FLAGS", "uint8"), + ("OVS_FLOW_ATTR_USED", "uint64"), + ("OVS_FLOW_ATTR_CLEAR", "none"), + ("OVS_FLOW_ATTR_MASK", "nested"), + ("OVS_FLOW_ATTR_PROBE", "none"), + ("OVS_FLOW_ATTR_UFID", "array(uint32)"), + ("OVS_FLOW_ATTR_UFID_FLAGS", "uint32"), + ) + + class nestedacts(nla): + __slots__ = () + + nla_map = () + + class flowstats(nla): + fields = ( + ("packets", "=Q"), + ("bytes", "=Q"), + ) + + class nestedflow(nla): + nla_map = ( + ("OVS_KEY_ATTR_UNSPEC", "none"), + ("OVS_KEY_ATTR_ENCAP", "none"), + ("OVS_KEY_ATTR_PRIORITY", "uint32"), + ("OVS_KEY_ATTR_IN_PORT", "uint32"), + ("OVS_KEY_ATTR_ETHERNET", "ethaddr"), + ("OVS_KEY_ATTR_VLAN", "uint16"), + ("OVS_KEY_ATTR_ETHERTYPE", "be16"), + ("OVS_KEY_ATTR_IPV4", "ovs_key_ipv4"), + ("OVS_KEY_ATTR_IPV6", "ovs_key_ipv6"), + ("OVS_KEY_ATTR_TCP", "ovs_key_tcp"), + ("OVS_KEY_ATTR_UDP", "ovs_key_udp"), + ("OVS_KEY_ATTR_ICMP", "ovs_key_icmp"), + ("OVS_KEY_ATTR_ICMPV6", "ovs_key_icmpv6"), + ("OVS_KEY_ATTR_ARP", "ovs_key_arp"), + ("OVS_KEY_ATTR_ND", "ovs_key_nd"), + ("OVS_KEY_ATTR_SKB_MARK", "uint32"), + ("OVS_KEY_ATTR_TUNNEL", "none"), + ("OVS_KEY_ATTR_SCTP", "ovs_key_sctp"), + ("OVS_KEY_ATTR_TCP_FLAGS", "uint16"), + ("OVS_KEY_ATTR_DP_HASH", "uint32"), + ("OVS_KEY_ATTR_RECIRC_ID", "uint32"), + ("OVS_KEY_ATTR_MPLS", "array(ovs_key_mpls)"), + ("OVS_KEY_ATTR_CT_STATE", "uint32"), + ("OVS_KEY_ATTR_CT_ZONE", "uint16"), + ("OVS_KEY_ATTR_CT_MARK", "uint32"), + ("OVS_KEY_ATTR_CT_LABELS", "none"), + ("OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4", "ovs_key_ct_tuple_ipv4"), + ("OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6", "ovs_key_ct_tuple_ipv6"), + ("OVS_KEY_ATTR_NSH", "none"), + ("OVS_KEY_ATTR_PACKET_TYPE", "none"), + ("OVS_KEY_ATTR_ND_EXTENSIONS", "none"), + ("OVS_KEY_ATTR_TUNNEL_INFO", "none"), + ("OVS_KEY_ATTR_IPV6_EXTENSIONS", "none"), + ) + + class ovs_key_proto(nla): + fields = ( + ("src", "!H"), + ("dst", "!H"), + ) + + fields_map = ( + ("src", "src", "%d", int), + ("dst", "dst", "%d", int), + ) + + def __init__( + self, + protostr, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + self.proto_str = protostr + nla.__init__( + self, + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + def dpstr(self, masked=None, more=False): + outstr = self.proto_str + "(" + first = False + for f in self.fields_map: + if first: + outstr += "," + if masked is None: + outstr += "%s=" % f[0] + if isinstance(f[2], str): + outstr += f[2] % self[f[1]] + else: + outstr += f[2](self[f[1]]) + first = True + elif more or f[3](masked[f[1]]) != 0: + outstr += "%s=" % f[0] + if isinstance(f[2], str): + outstr += f[2] % self[f[1]] + else: + outstr += f[2](self[f[1]]) + outstr += "/" + if isinstance(f[2], str): + outstr += f[2] % masked[f[1]] + else: + outstr += f[2](masked[f[1]]) + first = True + outstr += ")" + return outstr + + class ethaddr(ovs_key_proto): + fields = ( + ("src", "!6s"), + ("dst", "!6s"), + ) + + fields_map = ( + ("src", "src", macstr, lambda x: int.from_bytes(x, "big")), + ("dst", "dst", macstr, lambda x: int.from_bytes(x, "big")), + ) + + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "eth", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_ipv4(ovs_key_proto): + fields = ( + ("src", "!I"), + ("dst", "!I"), + ("proto", "B"), + ("tos", "B"), + ("ttl", "B"), + ("frag", "B"), + ) + + fields_map = ( + ( + "src", + "src", + lambda x: str(ipaddress.IPv4Address(x)), + int, + ), + ( + "dst", + "dst", + lambda x: str(ipaddress.IPv4Address(x)), + int, + ), + ("proto", "proto", "%d", int), + ("tos", "tos", "%d", int), + ("ttl", "ttl", "%d", int), + ("frag", "frag", "%d", int), + ) + + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "ipv4", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_ipv6(ovs_key_proto): + fields = ( + ("src", "!16s"), + ("dst", "!16s"), + ("label", "!I"), + ("proto", "B"), + ("tclass", "B"), + ("hlimit", "B"), + ("frag", "B"), + ) + + fields_map = ( + ( + "src", + "src", + lambda x: str(ipaddress.IPv6Address(x)), + lambda x: int.from_bytes(x, "big"), + ), + ( + "dst", + "dst", + lambda x: str(ipaddress.IPv6Address(x)), + lambda x: int.from_bytes(x, "big"), + ), + ("label", "label", "%d", int), + ("proto", "proto", "%d", int), + ("tclass", "tclass", "%d", int), + ("hlimit", "hlimit", "%d", int), + ("frag", "frag", "%d", int), + ) + + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "ipv6", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_tcp(ovs_key_proto): + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "tcp", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_udp(ovs_key_proto): + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "udp", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_sctp(ovs_key_proto): + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "sctp", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_icmp(ovs_key_proto): + fields = ( + ("type", "B"), + ("code", "B"), + ) + + fields_map = ( + ("type", "type", "%d", int), + ("code", "code", "%d", int), + ) + + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "icmp", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_icmpv6(ovs_key_icmp): + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "icmpv6", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_arp(ovs_key_proto): + fields = ( + ("sip", "!I"), + ("tip", "!I"), + ("op", "!H"), + ("sha", "!6s"), + ("tha", "!6s"), + ("pad", "xx"), + ) + + fields_map = ( + ( + "sip", + "sip", + lambda x: str(ipaddress.IPv4Address(x)), + int, + ), + ( + "tip", + "tip", + lambda x: str(ipaddress.IPv4Address(x)), + int, + ), + ("op", "op", "%d", int), + ("sha", "sha", macstr, lambda x: int.from_bytes(x, "big")), + ("tha", "tha", macstr, lambda x: int.from_bytes(x, "big")), + ) + + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "arp", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_nd(ovs_key_proto): + fields = ( + ("target", "!16s"), + ("sll", "!6s"), + ("tll", "!6s"), + ) + + fields_map = ( + ( + "target", + "target", + lambda x: str(ipaddress.IPv6Address(x)), + lambda x: int.from_bytes(x, "big"), + ), + ("sll", "sll", macstr, lambda x: int.from_bytes(x, "big")), + ("tll", "tll", macstr, lambda x: int.from_bytes(x, "big")), + ) + + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "nd", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_ct_tuple_ipv4(ovs_key_proto): + fields = ( + ("src", "!I"), + ("dst", "!I"), + ("tp_src", "!H"), + ("tp_dst", "!H"), + ("proto", "B"), + ) + + fields_map = ( + ( + "src", + "src", + lambda x: str(ipaddress.IPv4Address(x)), + int, + ), + ( + "dst", + "dst", + lambda x: str(ipaddress.IPv6Address(x)), + int, + ), + ("tp_src", "tp_src", "%d", int), + ("tp_dst", "tp_dst", "%d", int), + ("proto", "proto", "%d", int), + ) + + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "ct_tuple4", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_ct_tuple_ipv6(nla): + fields = ( + ("src", "!16s"), + ("dst", "!16s"), + ("tp_src", "!H"), + ("tp_dst", "!H"), + ("proto", "B"), + ) + + fields_map = ( + ( + "src", + "src", + lambda x: str(ipaddress.IPv6Address(x)), + lambda x: int.from_bytes(x, "big"), + ), + ( + "dst", + "dst", + lambda x: str(ipaddress.IPv6Address(x)), + lambda x: int.from_bytes(x, "big"), + ), + ("tp_src", "tp_src", "%d", int), + ("tp_dst", "tp_dst", "%d", int), + ("proto", "proto", "%d", int), + ) + + def __init__( + self, + data=None, + offset=None, + parent=None, + length=None, + init=None, + ): + OvsFlow.ovs_flow_msg.nestedflow.ovs_key_proto.__init__( + self, + "ct_tuple6", + data=data, + offset=offset, + parent=parent, + length=length, + init=init, + ) + + class ovs_key_mpls(nla): + fields = (("lse", ">I"),) + + def dpstr(self, mask=None, more=False): + print_str = "" + + for field in ( + ( + "OVS_KEY_ATTR_PRIORITY", + "skb_priority", + "%d", + lambda x: False, + True, + ), + ( + "OVS_KEY_ATTR_SKB_MARK", + "skb_mark", + "%d", + lambda x: False, + True, + ), + ( + "OVS_KEY_ATTR_RECIRC_ID", + "recirc_id", + "0x%08X", + lambda x: False, + True, + ), + ( + "OVS_KEY_ATTR_DP_HASH", + "dp_hash", + "0x%08X", + lambda x: False, + True, + ), + ( + "OVS_KEY_ATTR_CT_STATE", + "ct_state", + "0x%04x", + lambda x: False, + True, + ), + ( + "OVS_KEY_ATTR_CT_ZONE", + "ct_zone", + "0x%04x", + lambda x: False, + True, + ), + ( + "OVS_KEY_ATTR_CT_MARK", + "ct_mark", + "0x%08x", + lambda x: False, + True, + ), + ( + "OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4", + None, + None, + False, + False, + ), + ( + "OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6", + None, + None, + False, + False, + ), + ( + "OVS_KEY_ATTR_IN_PORT", + "in_port", + "%d", + lambda x: True, + True, + ), + ("OVS_KEY_ATTR_ETHERNET", None, None, False, False), + ( + "OVS_KEY_ATTR_ETHERTYPE", + "eth_type", + "0x%04x", + lambda x: int(x) == 0xFFFF, + True, + ), + ("OVS_KEY_ATTR_IPV4", None, None, False, False), + ("OVS_KEY_ATTR_IPV6", None, None, False, False), + ("OVS_KEY_ATTR_ARP", None, None, False, False), + ("OVS_KEY_ATTR_TCP", None, None, False, False), + ( + "OVS_KEY_ATTR_TCP_FLAGS", + "tcp_flags", + "0x%04x", + lambda x: False, + True, + ), + ("OVS_KEY_ATTR_UDP", None, None, False, False), + ("OVS_KEY_ATTR_SCTP", None, None, False, False), + ("OVS_KEY_ATTR_ICMP", None, None, False, False), + ("OVS_KEY_ATTR_ICMPV6", None, None, False, False), + ("OVS_KEY_ATTR_ND", None, None, False, False), + ): + v = self.get_attr(field[0]) + if v is not None: + m = None if mask is None else mask.get_attr(field[0]) + if field[4] is False: + print_str += v.dpstr(m, more) + print_str += "," + else: + if m is None or field[3](m): + print_str += field[1] + "(" + print_str += field[2] % v + print_str += ")," + elif more or m != 0: + print_str += field[1] + "(" + print_str += ( + (field[2] % v) + "/" + (field[2] % m) + ) + print_str += ")," + + return print_str + + def dpstr(self, more=False): + ufid = self.get_attr("OVS_FLOW_ATTR_UFID") + ufid_str = "" + if ufid is not None: + ufid_str = ( + "ufid:{:08x}-{:04x}-{:04x}-{:04x}-{:04x}{:08x}".format( + ufid[0], + ufid[1] >> 16, + ufid[1] & 0xFFFF, + ufid[2] >> 16, + ufid[2] & 0, + ufid[3], + ) + ) + + key_field = self.get_attr("OVS_FLOW_ATTR_KEY") + keymsg = None + if key_field is not None: + keymsg = OvsFlow.ovs_flow_msg.nestedflow(data=key_field) + keymsg.decode() + + mask_field = self.get_attr("OVS_FLOW_ATTR_MASK") + maskmsg = None + if mask_field is not None: + maskmsg = OvsFlow.ovs_flow_msg.nestedflow(data=mask_field) + maskmsg.decode() + + acts_field = self.get_attr("OVS_FLOW_ATTR_ACTIONS") + actsmsg = None + if acts_field is not None: + actsmsg = OvsFlow.ovs_flow_msg.nestedacts(data=acts_field) + actsmsg.decode() + + print_str = "" + + if more: + print_str += ufid_str + "," + + if keymsg is not None: + print_str += keymsg.dpstr(maskmsg, more) + + stats = self.get_attr("OVS_FLOW_ATTR_STATS") + if stats is None: + print_str += " packets:0, bytes:0," + else: + print_str += " packets:%d, bytes:%d," % ( + stats["packets"], + stats["bytes"], + ) + + used = self.get_attr("OVS_FLOW_ATTR_USED") + print_str += " used:" + if used is None: + print_str += "never," + else: + used_time = int(used) + cur_time_sec = time.clock_gettime(time.CLOCK_MONOTONIC) + used_time = (cur_time_sec * 1000 * 1000) - used_time + print_str += "{}s,".format(used_time / 1000) + + print_str += " actions:" + if actsmsg is None or "attrs" not in actsmsg: + print_str += "drop" + + return print_str + + def __init__(self): + GenericNetlinkSocket.__init__(self) + self.bind(OVS_FLOW_FAMILY, OvsFlow.ovs_flow_msg) + + def dump(self, dpifindex, flowspec=None): + """ + Returns a list of messages containing flows. + + dpifindex should be a valid datapath obtained by calling + into the OvsDatapath lookup + + flowpsec is a string which represents a flow in the dpctl + format. + """ + msg = OvsFlow.ovs_flow_msg() + + msg["cmd"] = OVS_FLOW_CMD_GET + msg["version"] = OVS_DATAPATH_VERSION + msg["reserved"] = 0 + msg["dpifindex"] = dpifindex + + msg_flags = NLM_F_REQUEST | NLM_F_ACK + if flowspec is None: + msg_flags |= NLM_F_DUMP + rep = None + + try: + rep = self.nlm_request( + msg, + msg_type=self.prid, + msg_flags=msg_flags, + ) + except NetlinkError as ne: + raise ne + return rep + + def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB(), vpl=OvsVport()): dp_name = dp_lookup_rep.get_attr("OVS_DP_ATTR_NAME") base_stats = dp_lookup_rep.get_attr("OVS_DP_ATTR_STATS") @@ -348,6 +1111,7 @@ def main(argv): "--verbose", action="count", help="Increment 'verbose' output counter.", + default=0, ) subparsers = parser.add_subparsers() @@ -389,10 +1153,18 @@ def main(argv): delifcmd.add_argument("dpname", help="Datapath Name") delifcmd.add_argument("delif", help="Interface name for adding") + dumpflcmd = subparsers.add_parser("dump-flows") + dumpflcmd.add_argument("dumpdp", help="Datapath Name") + args = parser.parse_args() + if args.verbose > 0: + if args.verbose > 1: + logging.basicConfig(level=logging.DEBUG) + ovsdp = OvsDatapath() ovsvp = OvsVport() + ovsflow = OvsFlow() ndb = NDB() if hasattr(args, "showdp"): @@ -445,7 +1217,14 @@ def main(argv): else: msg += " failed to remove." print(msg) - + elif hasattr(args, "dumpdp"): + rep = ovsdp.info(args.dumpdp, 0) + if rep is None: + print("DP '%s' not found." % args.dumpdp) + return 1 + rep = ovsflow.dump(rep["dpifindex"]) + for flow in rep: + print(flow.dpstr(True if args.verbose > 0 else False)) return 0 From patchwork Tue Nov 22 14:03:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 24393 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2219398wrr; Tue, 22 Nov 2022 06:09:51 -0800 (PST) X-Google-Smtp-Source: AA0mqf6rydmptpEjnYLxoYHjZBFPAfwH4kDf1JnhnRlBf+M0RW2iyfCgC0RB4dyiujtCtLh+Z/gb X-Received: by 2002:a17:902:a50d:b0:188:547d:b15e with SMTP id s13-20020a170902a50d00b00188547db15emr4728324plq.50.1669126190981; Tue, 22 Nov 2022 06:09:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669126190; cv=none; d=google.com; s=arc-20160816; b=jWUnCrU0Nk76S2rs7OzSErixm5mTYcT8UUSfsajHo3iIBkSirgfRlE2kEL+mWHU84+ DXM5Fcr6Q0iRFf719Q50GkL9I8nHsrG3qvXNPSQmbkbX2VYpvq9vbmpYlt8JqUq4JZYT b4vQk9PzbKAQxkRTCKCeEO9kcqiPzaNeBXu63QQXe2pv2B5rYORfJc/blTGcGECAyBYF WUk3uu7kWX9kuKNEGpo2lbhDXbFLP/J7q02qwUO4jDYvNusdquVdJ+mwL/Ryq1XIQz79 C9QpjaZlrLSToqTfQUofjpYa8vvpCrCkZlLlow55J/Hf00oZxjrC8L8btzoY2LlSWjNm NiHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=FiZt6CO0d2Q/fNRLdOiB+spVHV87735/SJe/WQ/NZzg=; b=sfJXGfl+jfqZv7SiwgsK9Nf8oBNwDYEwTln9K1MzWbMFh+xmSpu5nQk9dotDTeyB/Y wfDKcx0+0bTuq0xHXx+oJfylNb8M9LzdqfI49tfW2YyqFoWa6kkn1fVReg6oiDPuG7Mm /lCFDpEubUb2PL6W/m3M1qsqDZzSlYbbRnn25SSj35uj5XUlxQgjO8Gx1VXRln3Agd38 QQ6dxJptAZfieO1U4YKy7qP3j4R4wfEnXXutm5SDGCwjS0pJFAIOaQIU3slGf6MZIL+j mFuS5k39po/5x9qmtJmvpqXm3+tcGch55aWPruVNJo+qS3FDYZ8gKo4BnPBH0587TaTP F7Pw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ZK9QIdWD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id y27-20020a63181b000000b0047698f9d889si14037130pgl.188.2022.11.22.06.09.29; Tue, 22 Nov 2022 06:09:50 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ZK9QIdWD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233995AbiKVOF6 (ORCPT + 99 others); Tue, 22 Nov 2022 09:05:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55766 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233976AbiKVOFO (ORCPT ); Tue, 22 Nov 2022 09:05:14 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 58B381EEFF for ; Tue, 22 Nov 2022 06:03:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669125796; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FiZt6CO0d2Q/fNRLdOiB+spVHV87735/SJe/WQ/NZzg=; b=ZK9QIdWDVtosfcG8457VQvFEXexdYFE1GWIm/cabYV2+KvJCty5zOM5eTC+uXf4Ho0na9P +hSWIEaV/PER8np1yvGYF97ExQIJJsBkg68s9VM3lk9GmTM/7CtDTIeoRCtSORRWRGibYm KDY38ZzkIAym5W3EodLpQMnzxFIa7Lo= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-609-KbIRkdF1M_2eJfwfZ3i_ZA-1; Tue, 22 Nov 2022 09:03:14 -0500 X-MC-Unique: KbIRkdF1M_2eJfwfZ3i_ZA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 73174801585; Tue, 22 Nov 2022 14:03:13 +0000 (UTC) Received: from RHTPC1VM0NT.redhat.com (unknown [10.22.16.203]) by smtp.corp.redhat.com (Postfix) with ESMTP id DE54040C6EC6; Tue, 22 Nov 2022 14:03:11 +0000 (UTC) From: Aaron Conole To: netdev@vger.kernel.org Cc: Pravin B Shelar , Jakub Kicinski , "David S. Miller" , Paolo Abeni , Eric Dumazet , Thomas Graf , dev@openvswitch.org, Eelco Chaudron , Ilya Maximets , Shuah Khan , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [RFC net-next 4/6] selftests: openvswitch: adjust datapath NL message Date: Tue, 22 Nov 2022 09:03:05 -0500 Message-Id: <20221122140307.705112-5-aconole@redhat.com> In-Reply-To: <20221122140307.705112-1-aconole@redhat.com> References: <20221122140307.705112-1-aconole@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750205664670980956?= X-GMAIL-MSGID: =?utf-8?q?1750205664670980956?= The netlink message for creating a new datapath takes an array of ports for the PID creation. This shouldn't cause much issue but correct it for future messages where we need to do decode of datapath information that could include the per-cpu PID map Fixes: 25f16c873fb1 ("selftests: add openvswitch selftest suite") Signed-off-by: Aaron Conole --- tools/testing/selftests/net/openvswitch/ovs-dpctl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py index d654fe1fe4e6..fe14da358901 100644 --- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py +++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py @@ -71,7 +71,7 @@ class OvsDatapath(GenericNetlinkSocket): nla_map = ( ("OVS_DP_ATTR_UNSPEC", "none"), ("OVS_DP_ATTR_NAME", "asciiz"), - ("OVS_DP_ATTR_UPCALL_PID", "uint32"), + ("OVS_DP_ATTR_UPCALL_PID", "array(uint32)"), ("OVS_DP_ATTR_STATS", "dpstats"), ("OVS_DP_ATTR_MEGAFLOW_STATS", "megaflowstats"), ("OVS_DP_ATTR_USER_FEATURES", "uint32"), @@ -141,7 +141,7 @@ class OvsDatapath(GenericNetlinkSocket): msg["attrs"].append(["OVS_DP_ATTR_USER_FEATURES", dpfeatures]) if not shouldUpcall: - msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", 0]) + msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", [0]]) try: reply = self.nlm_request( From patchwork Tue Nov 22 14:03:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 24399 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2220224wrr; Tue, 22 Nov 2022 06:11:13 -0800 (PST) X-Google-Smtp-Source: AA0mqf6ZwktDTyfE/EvpJN3Jyv8jlLR8y/uBQ65DAcGAS3RtXy5KwTYN7E/8hBiLAPptp2P1QQbw X-Received: by 2002:a17:903:2798:b0:186:61a7:aea1 with SMTP id jw24-20020a170903279800b0018661a7aea1mr16982718plb.145.1669126272967; Tue, 22 Nov 2022 06:11:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669126272; cv=none; d=google.com; s=arc-20160816; b=ldpoJAH+HUOkb9ffl9sCFJOqxdEfzAvx4BdUUkqZexOl5MxmRYQ7Cnqv4s8op754o1 i8p4yEkDoj+ue7A44/r5J+uhahQJfRTT82/AwcMauJAz2iWRdA8noLFTeaR6IOttO15t /hySo01i828yIaBljjJkCkYhSfeCCrvY346iCGm2FHqS62ByTdaz6zgE57jPGlQPucqw 9k0F9bR87ot0bqk70q0Elfnzwj+i4m77UgR9xq7hQSZC3dVSIYAYQ0Q/Cen3rnd3yXMU iiov94guiTi4AgnM3+Z/uJTdLzPybjPsXX6JStkztNsSGlg+l8bFsYfmw9nqICZ8C20A ZtPA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=D+4flvqengNNBgDwPRdu4ptsudDd6Mu7MlqZ94ZwyBM=; b=slZmLZTgHYzB0NI/hJW4pSAyCqGCyq2OmKnATBYObnc7FX9lBd5uPjMc3RD12HBX6T weaSLJ5z0TBpf7tqzMgfm/Uzkjn6dUbyu/UbH6bK7sCfZ4KGuoMKR2Z9IiQwBETrf5ty IosFdQU9t30uLBmaptXlqrgtdubrNVrfSN/LlsUieMfEt/Nb9nWC32w+XbZMNQImsLr6 yrM2NiT4bP3lqxZuy3mUH3WPra8yBk0MvM6J82HmquO6MUJpn59q4+vFQjLP5gYAqy8E OfA5jX2335KgVCJiwokqbJSV1xjFf4C2J7VyVKJ+Fuvd73OUiPauXVEo1YwOBNZeinqa JdNw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="VM/1APKN"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id s2-20020a17090302c200b00176d22a068csi12517303plk.515.2022.11.22.06.10.50; Tue, 22 Nov 2022 06:11:12 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="VM/1APKN"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234034AbiKVOGo (ORCPT + 99 others); Tue, 22 Nov 2022 09:06:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55770 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232779AbiKVOGE (ORCPT ); Tue, 22 Nov 2022 09:06:04 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CA7FF20F50 for ; Tue, 22 Nov 2022 06:03:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669125801; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=D+4flvqengNNBgDwPRdu4ptsudDd6Mu7MlqZ94ZwyBM=; b=VM/1APKNvXChyYigurAbm19lmNeznTJ5CwAYgvKBKSqgLcw3nbDrqwJqwhdppnsuM9cwbG 31ktWHD9oVLV5RvgzHVyhnPCdEEXqWDhKi/UfjxQgJovCMXOVgZuHaF+i3qyTEyYQUHE5U dLbpUr8dbOSaeooNDJytXUwhrqzoy9k= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-119-Yl-nshPSMeqNYM-1s8XnDg-1; Tue, 22 Nov 2022 09:03:16 -0500 X-MC-Unique: Yl-nshPSMeqNYM-1s8XnDg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 7E67C3C0F231; Tue, 22 Nov 2022 14:03:15 +0000 (UTC) Received: from RHTPC1VM0NT.redhat.com (unknown [10.22.16.203]) by smtp.corp.redhat.com (Postfix) with ESMTP id 83EB740C6EC6; Tue, 22 Nov 2022 14:03:13 +0000 (UTC) From: Aaron Conole To: netdev@vger.kernel.org Cc: Pravin B Shelar , Jakub Kicinski , "David S. Miller" , Paolo Abeni , Eric Dumazet , Thomas Graf , dev@openvswitch.org, Eelco Chaudron , Ilya Maximets , Shuah Khan , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [RFC net-next 5/6] selftests: openvswitch: add upcall support Date: Tue, 22 Nov 2022 09:03:06 -0500 Message-Id: <20221122140307.705112-6-aconole@redhat.com> In-Reply-To: <20221122140307.705112-1-aconole@redhat.com> References: <20221122140307.705112-1-aconole@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750205750373209902?= X-GMAIL-MSGID: =?utf-8?q?1750205750373209902?= Future tests can make use of CMD_MISS events to do things like cross validated packet contents with the flow key that was generated by flow key extraction. This will also be used in an upcoming commit to allow removing the flow key from upcall messages. Signed-off-by: Aaron Conole --- .../selftests/net/openvswitch/ovs-dpctl.py | 140 +++++++++++++++++- 1 file changed, 133 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py index fe14da358901..94204af48d28 100644 --- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py +++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py @@ -8,6 +8,8 @@ import argparse import errno import ipaddress import logging +import multiprocessing +import struct import sys import time @@ -58,6 +60,53 @@ class ovs_dp_msg(genlmsg): fields = genlmsg.fields + (("dpifindex", "I"),) +class OvsPacket(GenericNetlinkSocket): + OVS_PACKET_CMD_MISS = 1 # Flow table miss + OVS_PACKET_CMD_ACTION = 2 # USERSPACE action + OVS_PACKET_CMD_EXECUTE = 3 # Apply actions to packet + + class ovs_packet_msg(ovs_dp_msg): + nla_map = ( + ('OVS_PACKET_ATTR_UNSPEC', 'none'), + ('OVS_PACKET_ATTR_PACKET', 'array(uint8)'), + ('OVS_PACKET_ATTR_KEY', 'nested'), + ('OVS_PACKET_ATTR_ACTIONS', 'nested'), + ('OVS_PACKET_ATTR_USERDATA', 'nested'), + ('OVS_PACKET_ATTR_EGRESS_TUN_KEY', 'nested'), + ('OVS_PACKET_ATTR_UNUSED1', 'none'), + ('OVS_PACKET_ATTR_UNUSED2', 'none'), + ('OVS_PACKET_ATTR_PROBE', 'none'), + ('OVS_PACKET_ATTR_MRU', 'uint16'), + ('OVS_PACKET_ATTR_LEN', 'uint32'), + ('OVS_PACKET_ATTR_HASH', 'uint64'), + ) + + def __init__(self): + GenericNetlinkSocket.__init__(self) + print("Binding to packet family") + self.bind(OVS_PACKET_FAMILY, OvsPacket.ovs_packet_msg) + print("Port", self.epid) + + def upcall_handler(self, up=None): + print("listening on upcall packet handler:", self.epid) + while True: + try: + msgs = self.get() + for msg in msgs: + if not up: + continue + if msg["cmd"] == OvsPacket.OVS_PACKET_CMD_MISS: + up.miss(msg) + elif msg["cmd"] == OvsPacket.OVS_PACKET_CMD_ACTION: + up.action(msg) + elif msg["cmd"] == OvsPacket.OVS_PACKET_CMD_EXECUTE: + up.execute(msg) + else: + print("Unkonwn cmd: %d" % msg["cmd"]) + except NetlinkError as ne: + raise ne + + class OvsDatapath(GenericNetlinkSocket): OVS_DP_F_VPORT_PIDS = 1 << 1 @@ -122,7 +171,7 @@ class OvsDatapath(GenericNetlinkSocket): return reply - def create(self, dpname, shouldUpcall=False, versionStr=None): + def create(self, dpname, shouldUpcall=False, versionStr=None, p=OvsPacket()): msg = OvsDatapath.dp_cmd_msg() msg["cmd"] = OVS_DP_CMD_NEW if versionStr is None: @@ -139,9 +188,19 @@ class OvsDatapath(GenericNetlinkSocket): else: dpfeatures = OvsDatapath.OVS_DP_F_VPORT_PIDS - msg["attrs"].append(["OVS_DP_ATTR_USER_FEATURES", dpfeatures]) if not shouldUpcall: msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", [0]]) + else: + if versionStr is None or versionStr.find(":") == -1: + dpfeatures |= OvsDatapath.OVS_DP_F_DISPATCH_UPCALL_PER_CPU + dpfeatures &= ~OvsDatapath.OVS_DP_F_VPORT_PIDS + + nproc = multiprocessing.cpu_count() + procarray = [] + for i in range(1, nproc): + procarray += [int(p.epid)] + msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", procarray]) + msg["attrs"].append(["OVS_DP_ATTR_USER_FEATURES", dpfeatures]) try: reply = self.nlm_request( @@ -238,9 +297,10 @@ class OvsVport(GenericNetlinkSocket): return OvsVport.OVS_VPORT_TYPE_GENEVE raise ValueError("Unknown vport type: '%s'" % vport_type) - def __init__(self): + def __init__(self, packet=OvsPacket()): GenericNetlinkSocket.__init__(self) self.bind(OVS_VPORT_FAMILY, OvsVport.ovs_vport_msg) + self.upcall_packet = packet def info(self, vport_name, dpifindex=0, portno=None): msg = OvsVport.ovs_vport_msg() @@ -278,7 +338,36 @@ class OvsVport(GenericNetlinkSocket): msg["attrs"].append(["OVS_VPORT_ATTR_TYPE", port_type]) msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) - msg["attrs"].append(["OVS_VPORT_ATTR_UPCALL_PID", [self.pid]]) + msg["attrs"].append(["OVS_VPORT_ATTR_UPCALL_PID", + [self.upcall_packet.epid]]) + + try: + reply = self.nlm_request( + msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK + ) + reply = reply[0] + except NetlinkError as ne: + if ne.code == errno.EEXIST: + reply = None + else: + raise ne + return reply + + def reset_upcall(self, dpindex, vport_ifname, p=None): + msg = OvsVport.ovs_vport_msg() + + msg["cmd"] = OVS_VPORT_CMD_SET + msg["version"] = OVS_DATAPATH_VERSION + msg["reserved"] = 0 + msg["dpifindex"] = dpindex + msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) + + if p == None: + p = self.upcall_packet + else: + self.upcall_packet = p + + msg["attrs"].append(["OVS_VPORT_ATTR_UPCALL_PID", [p.epid]]) try: reply = self.nlm_request( @@ -310,6 +399,9 @@ class OvsVport(GenericNetlinkSocket): raise ne return reply + def upcall_handler(self, handler=None): + self.upcall_packet.upcall_handler(handler) + def macstr(mac): outstr = ":".join(["%02X" % i for i in mac]) @@ -1064,6 +1156,26 @@ class OvsFlow(GenericNetlinkSocket): raise ne return rep + def miss(self, packetmsg): + seq = packetmsg["header"]["sequence_number"] + keystr = "(none)" + key_field = packetmsg.get_attr("OVS_PACKET_ATTR_KEY") + if key_field is not None: + keymsg = OvsFlow.ovs_flow_msg.nestedflow(data=key_field) + keymsg.decode() + keystr = keymsg.dpstr(None, True) + + pktdata = packetmsg.get_attr("OVS_PACKET_ATTR_PACKET") + pktpres = "yes" if pktdata is not None else "no" + + print("MISS upcall[%d/%s]: %s" % (seq, pktpres, keystr), flush = True) + + def execute(self, packetmsg): + print("userspace execute command") + + def action(self, packetmsg): + print("userspace action command") + def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB(), vpl=OvsVport()): dp_name = dp_lookup_rep.get_attr("OVS_DP_ATTR_NAME") @@ -1141,6 +1253,12 @@ def main(argv): addifcmd = subparsers.add_parser("add-if") addifcmd.add_argument("dpname", help="Datapath Name") addifcmd.add_argument("addif", help="Interface name for adding") + addifcmd.add_argument( + "-u", + "--upcall", + action="store_true", + help="Leave open a reader for upcalls", + ) addifcmd.add_argument( "-t", "--ptype", @@ -1162,8 +1280,9 @@ def main(argv): if args.verbose > 1: logging.basicConfig(level=logging.DEBUG) + ovspk = OvsPacket() ovsdp = OvsDatapath() - ovsvp = OvsVport() + ovsvp = OvsVport(ovspk) ovsflow = OvsFlow() ndb = NDB() @@ -1186,11 +1305,13 @@ def main(argv): msg += ":'%s'" % args.showdp print(msg) elif hasattr(args, "adddp"): - rep = ovsdp.create(args.adddp, args.upcall, args.versioning) + rep = ovsdp.create(args.adddp, args.upcall, args.versioning, ovspk) if rep is None: print("DP '%s' already exists" % args.adddp) else: print("DP '%s' added" % args.adddp) + if args.upcall: + ovspk.upcall_handler(ovsflow) elif hasattr(args, "deldp"): ovsdp.destroy(args.deldp) elif hasattr(args, "addif"): @@ -1198,13 +1319,18 @@ def main(argv): if rep is None: print("DP '%s' not found." % args.dpname) return 1 - rep = ovsvp.attach(rep["dpifindex"], args.addif, args.ptype) + dpindex = rep["dpifindex"] + rep = ovsvp.attach(dpindex, args.addif, args.ptype) msg = "vport '%s'" % args.addif if rep and rep["error"] == 0: msg += " added." else: msg += " failed to add." print(msg) + if args.upcall: + if rep is None: + rep = ovsvp.reset_upcall(dpindex, args.addif, ovspk) + ovsvp.upcall_handler(ovsflow) elif hasattr(args, "delif"): rep = ovsdp.info(args.dpname, 0) if rep is None: From patchwork Tue Nov 22 14:03:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 24395 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2219623wrr; Tue, 22 Nov 2022 06:10:13 -0800 (PST) X-Google-Smtp-Source: AA0mqf6ZoHLwVuM6IobQUL5iGuWp95RODwBXFKFJDuk0Vptfk6umXklyWb947yPqnuv1Ois9scAH X-Received: by 2002:a17:90a:c685:b0:218:7b33:60c with SMTP id n5-20020a17090ac68500b002187b33060cmr23905256pjt.99.1669126212886; Tue, 22 Nov 2022 06:10:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669126212; cv=none; d=google.com; s=arc-20160816; b=zzVR0zb6PTGY9dxYJdRezNfoQ2U5XeomrRG+/jua6MblYOovUcJLWuxddmdkaaQZ1k VFGiiL2vx2S54YgJrWV7b8yx9BOf+NtsDmR/8Fr2FtXhpiWF/8SDnunecnthl/dC4zKF bZP419gUeBKX/sByqbe2LBsvf4lRlCQDYc6zevRThUqbVIYoZNzG8H6NRiZPBaADR9Ij cw6O645ueqfEw2GAHp+DcAZ1wmRDgoYJAP/fzkZihH0LXs73twW8Zjb+QZ/bXUHlTOfw vFuGty2Juw/l0YwIKhi32I5gLX5HaZFL/y+aSnZYXkWK6kJPb5fZrvG8Pc7pWuImk9PW qoUg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=rYhRWhA1aSMDmEn1uPY3m1Uoc/nxJhjisw6iqoh6KAk=; b=gvas9CxIWUZx63MCUzvIVvNwYei0Etd9NXSUxqELA2/FlajNoXZW8JzZedKDdFQ9LQ 1Xim2YFLyUQvHxrMXiIkzdptVuT/oBg7YxnpEXG8G1k1FGvyLn4eAhDYRwaWXB1sERkl QeDP349Jz/gwE81SYqzc4yYhO682Ilb6aY4jgTzg3dOlVNHenBS/UPG2d9rOjnh0d80+ RBUZtfdDFBaan56XB0QF9mc+o2o8lFL427nPV1ZsBi/agWjUMGlbeKRvTLoOT2DMkiP1 58M8ozcxW3TsxKFuhPJ18NIrbKvLt9jLb6gyFa2pRsZJrWN2DUf0ICMyZZTYsN7hoafL IQyg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=L8Ykf4br; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u5-20020a627905000000b0056bb63ab519si12893404pfc.310.2022.11.22.06.09.51; Tue, 22 Nov 2022 06:10:12 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=L8Ykf4br; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234031AbiKVOGb (ORCPT + 99 others); Tue, 22 Nov 2022 09:06:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55784 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234080AbiKVOF5 (ORCPT ); Tue, 22 Nov 2022 09:05:57 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6A21920F41 for ; Tue, 22 Nov 2022 06:03:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669125799; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rYhRWhA1aSMDmEn1uPY3m1Uoc/nxJhjisw6iqoh6KAk=; b=L8Ykf4brRPMonsGs8Oeom3vT1zEGZg/HHZ6kNGE8Kgd4n2jY/POKZ31s+4DETNlv9sjEof CDjQb1AmMiRcIh1SAEKpsPWcHtwgLjgFC/dS5FOxPxC1TrLpWos2LuBwUCcElmgAVdc/3Y UecNpJnADkeickbXstDlqb4x+/veF9o= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-654-4mjhlybcObqbcyDAl7QVdg-1; Tue, 22 Nov 2022 09:03:16 -0500 X-MC-Unique: 4mjhlybcObqbcyDAl7QVdg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 12028973283; Tue, 22 Nov 2022 14:03:16 +0000 (UTC) Received: from RHTPC1VM0NT.redhat.com (unknown [10.22.16.203]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9132A40C6EC6; Tue, 22 Nov 2022 14:03:15 +0000 (UTC) From: Aaron Conole To: netdev@vger.kernel.org Cc: Pravin B Shelar , Jakub Kicinski , "David S. Miller" , Paolo Abeni , Eric Dumazet , Thomas Graf , dev@openvswitch.org, Eelco Chaudron , Ilya Maximets , Shuah Khan , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [RFC net-next 6/6] selftests: openvswitch: add exclude support for packet commands Date: Tue, 22 Nov 2022 09:03:07 -0500 Message-Id: <20221122140307.705112-7-aconole@redhat.com> In-Reply-To: <20221122140307.705112-1-aconole@redhat.com> References: <20221122140307.705112-1-aconole@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750205687595885576?= X-GMAIL-MSGID: =?utf-8?q?1750205687595885576?= Introduce a test case to show that we can exclude flows based on specific configurations. Signed-off-by: Aaron Conole --- .../selftests/net/openvswitch/openvswitch.sh | 53 +++++++++++++++++-- .../selftests/net/openvswitch/ovs-dpctl.py | 34 +++++++++++- 2 files changed, 81 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh index ce14913150fe..f04f2f748332 100755 --- a/tools/testing/selftests/net/openvswitch/openvswitch.sh +++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh @@ -11,7 +11,8 @@ VERBOSE=0 TRACING=0 tests=" - netlink_checks ovsnl: validate netlink attrs and settings" + netlink_checks ovsnl: validate netlink attrs and settings + upcall_interfaces ovs: test the upcall interfaces" info() { [ $VERBOSE = 0 ] || echo $* @@ -72,7 +73,15 @@ ovs_add_dp () { ovs_add_if () { info "Adding IF to DP: br:$2 if:$3" - ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-if "$2" "$3" || return 1 + if [ "$4" != "-u" ]; then + ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-if "$2" "$3" \ + || return 1 + else + python3 $ovs_base/ovs-dpctl.py add-if \ + -u "$2" "$3" >$ovs_dir/$3.out 2>$ovs_dir/$3.err & + pid=$! + on_exit "ovs_sbx $1 kill -TERM $pid 2>/dev/null" + fi } ovs_del_if () { @@ -103,10 +112,16 @@ ovs_add_netns_and_veths () { ovs_sbx "$1" ip netns exec "$3" ip link set "$5" up || return 1 if [ "$6" != "" ]; then - ovs_sbx "$1" ip netns exec "$4" ip addr add "$6" dev "$5" \ + ovs_sbx "$1" ip netns exec "$3" ip addr add "$6" dev "$5" \ || return 1 fi - ovs_add_if "$1" "$2" "$4" || return 1 + + if [ "$7" != "-u" ]; then + ovs_add_if "$1" "$2" "$4" || return 1 + else + ovs_add_if "$1" "$2" "$4" -u || return 1 + fi + [ $TRACING -eq 1 ] && ovs_netns_spawn_daemon "$1" "$3" \ tcpdump -i any -s 65535 >> ${ovs_dir}/tcpdump_"$3".log @@ -158,6 +173,36 @@ test_netlink_checks () { return 0 } +test_upcall_interfaces() { + sbx_add "test_upcall_interfaces" || return 1 + + info "setting up new DP" + ovs_add_dp "test_upcall_interfaces" ui0 || return 1 + + ovs_add_netns_and_veths "test_upcall_interfaces" ui0 upc left0 l0 \ + 172.31.110.1/24 -u || return 1 + + sleep 1 + info "sending arping" + ip netns exec upc arping -I l0 172.31.110.20 -c 1 \ + >$ovs_dir/arping.stdout 2>$ovs_dir/arping.stderr + + grep -E "MISS upcall\[0/yes\]: .*arp\(sip=172.31.110.1,tip=172.31.110.20,op=1,sha=" $ovs_dir/left0.out >/dev/null 2>&1 || return 1 + # now tear down the DP and set it up with the new options + ovs_sbx "test_upcall_interfaces" python3 $ovs_base/ovs-dpctl.py \ + del-dp ui0 || return 1 + ovs_sbx "test_upcall_interfaces" python3 $ovs_base/ovs-dpctl.py \ + add-dp -e miss -- ui0 || return 1 + ovs_add_if "test_upcall_interfaces" ui0 left0 -u || return 1 + + sleep 1 + info "sending second arping" + ip netns exec upc arping -I l0 172.31.110.20 -c 1 \ + >$ovs_dir/arping.stdout 2>$ovs_dir/arping.stderr + grep -E "MISS upcall\[0/yes\]: \(none\)" $ovs_dir/left0.out >/dev/null 2>&1 || return 1 + return 0 +} + run_test() { ( tname="$1" diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py index 94204af48d28..ba115fb51773 100644 --- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py +++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py @@ -111,6 +111,7 @@ class OvsDatapath(GenericNetlinkSocket): OVS_DP_F_VPORT_PIDS = 1 << 1 OVS_DP_F_DISPATCH_UPCALL_PER_CPU = 1 << 3 + OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY = 1 << 4 class dp_cmd_msg(ovs_dp_msg): """ @@ -127,6 +128,8 @@ class OvsDatapath(GenericNetlinkSocket): ("OVS_DP_ATTR_PAD", "none"), ("OVS_DP_ATTR_MASKS_CACHE_SIZE", "uint32"), ("OVS_DP_ATTR_PER_CPU_PIDS", "array(uint32)"), + ("OVS_DP_ATTR_IFINDEX", "uint32"), + ("OVS_DP_ATTR_EXCLUDE_CMDS", "uint32"), ) class dpstats(nla): @@ -171,7 +174,8 @@ class OvsDatapath(GenericNetlinkSocket): return reply - def create(self, dpname, shouldUpcall=False, versionStr=None, p=OvsPacket()): + def create(self, dpname, shouldUpcall=False, versionStr=None, p=OvsPacket(), + exclude=[]): msg = OvsDatapath.dp_cmd_msg() msg["cmd"] = OVS_DP_CMD_NEW if versionStr is None: @@ -200,6 +204,23 @@ class OvsDatapath(GenericNetlinkSocket): for i in range(1, nproc): procarray += [int(p.epid)] msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", procarray]) + + excluded = 0 + print("exclude", exclude) + if len(exclude) > 0: + for ex in exclude: + if ex == "miss": + excluded |= 1 << OvsPacket.OVS_PACKET_CMD_MISS + elif ex == "action": + excluded |= 1 << OvsPacket.OVS_PACKET_CMD_ACTION + elif ex == "execute": + excluded |= 1 << OvsPacket.OVS_PACKET_CMD_EXECUTE + else: + print("DP CREATE: Unknown type: '%s'" % ex) + msg["attrs"].append(["OVS_DP_ATTR_EXCLUDE_CMDS", excluded]) + if versionStr is None or versionStr.find(":") == -1: + dpfeatures |= OvsDatapath.OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY + msg["attrs"].append(["OVS_DP_ATTR_USER_FEATURES", dpfeatures]) try: @@ -1240,6 +1261,14 @@ def main(argv): action="store_true", help="Leave open a reader for upcalls", ) + adddpcmd.add_argument( + "-e", + "--exclude", + type=str, + default=[], + nargs="+", + help="Exclude flow key from upcall packet commands" + ) adddpcmd.add_argument( "-V", "--versioning", @@ -1305,7 +1334,8 @@ def main(argv): msg += ":'%s'" % args.showdp print(msg) elif hasattr(args, "adddp"): - rep = ovsdp.create(args.adddp, args.upcall, args.versioning, ovspk) + rep = ovsdp.create(args.adddp, args.upcall, args.versioning, ovspk, + args.exclude) if rep is None: print("DP '%s' already exists" % args.adddp) else: