From patchwork Thu Jul 4 07:52:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956702 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=F7DiUmVP; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (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 4WF85g4fCJz1xpP for ; Thu, 4 Jul 2024 17:53:11 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 1EBCB60B35; Thu, 4 Jul 2024 07:53:10 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id iWaof4-Equik; Thu, 4 Jul 2024 07:53:09 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org D3CA460796 Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=F7DiUmVP Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id D3CA460796; Thu, 4 Jul 2024 07:53:08 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id B6370C0A97; Thu, 4 Jul 2024 07:53:08 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id C2B36C0A99 for ; Thu, 4 Jul 2024 07:53:05 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id A8C9340186 for ; Thu, 4 Jul 2024 07:53:05 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id FM7jjkKN4FsZ for ; Thu, 4 Jul 2024 07:53:04 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp2.osuosl.org 5BECB401AE Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 5BECB401AE Authentication-Results: smtp2.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=F7DiUmVP Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp2.osuosl.org (Postfix) with ESMTPS id 5BECB401AE for ; Thu, 4 Jul 2024 07:53:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079582; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=86v7MAhGc2Vb/z3FJvhWh6aMlZFQ8Aw9VqnUuCbzV4w=; b=F7DiUmVPtLGQHk00K2Jmh/zXfhbuOhhUoLXXE5E8SUJAlvFdMMbakOIsKKFoAPdLayA0Zu zJWPxpAuOS6HtCbFkZ4SSUGhgenl3fzzU+nvrkY4lYxcl4lLVAvdBRsLWXrM0IO28X+o59 gtdvWfGaOopVXBaw7YIx4bFNIvY2jqc= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-317-rr5MqTo2P_uHEETj3INLfQ-1; Thu, 04 Jul 2024 03:53:00 -0400 X-MC-Unique: rr5MqTo2P_uHEETj3INLfQ-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id ABD291955F45 for ; Thu, 4 Jul 2024 07:52:59 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 87E7C1955F65; Thu, 4 Jul 2024 07:52:58 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:42 +0200 Message-ID: <20240704075255.140530-2-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 01/13] ofproto-dpif: Allow forcing dp features. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Datapath features can be set with dpif/set-dp-features unixctl command. This command is not docummented and therefore not supported in production but only useful for unit tests. A limitation was put in place originally to avoid enabling features at runtime that were disabled at boot time to avoid breaking the datapath in unexpected ways. But, considering users should not use this command and it should only be used for testing, we can assume whoever runs it knows what they are doing. Therefore, the limitation should be bypass-able. This patch adds a "--force" flag to the unixctl command to allow bypassing the mentioned limitation. Signed-off-by: Adrian Moreno --- ofproto/ofproto-dpif.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index fcd7cd753..4712d10a8 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -6432,7 +6432,8 @@ display_support_field(const char *name, static bool dpif_set_support(struct dpif_backer_support *rt_support, struct dpif_backer_support *bt_support, - const char *name, const char *value, struct ds *ds) + const char *name, const char *value, bool force, + struct ds *ds) { struct shash all_fields = SHASH_INITIALIZER(&all_fields); struct dpif_support_field *field; @@ -6484,8 +6485,8 @@ dpif_set_support(struct dpif_backer_support *rt_support, if (field->type == DPIF_SUPPORT_FIELD_bool) { if (!strcasecmp(value, "true")) { - if (*(bool *)field->bt_ptr) { - *(bool *)field->rt_ptr = true; + if (*(bool *) field->bt_ptr || force) { + *(bool *) field->rt_ptr = true; changed = true; } else { ds_put_cstr(ds, "Can not enable features not supported by the datapth"); @@ -6720,21 +6721,36 @@ ofproto_unixctl_dpif_set_dp_features(struct unixctl_conn *conn, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; - const char *br = argv[1]; + struct ofproto_dpif *ofproto; + bool changed, force = false; const char *name, *value; - struct ofproto_dpif *ofproto = ofproto_dpif_lookup_by_name(br); - bool changed; + const char *br = NULL; + + if (!strcmp(argv[1], "--force")) { + force = true; + if (argc > 2) { + br = argv[2]; + name = argc > 3 ? argv[3] : NULL; + value = argc > 4 ? argv[4] : NULL; + } else { + unixctl_command_reply_error(conn, "bridge not specified"); + return; + } + } else { + br = argv[1]; + name = argc > 2 ? argv[2] : NULL; + value = argc > 3 ? argv[3] : NULL; + } + ofproto = ofproto_dpif_lookup_by_name(br); if (!ofproto) { unixctl_command_reply_error(conn, "no such bridge"); return; } - name = argc > 2 ? argv[2] : NULL; - value = argc > 3 ? argv[3] : NULL; changed = dpif_set_support(&ofproto->backer->rt_support, &ofproto->backer->bt_support, - name, value, &ds); + name, value, force, &ds); if (changed) { xlate_set_support(ofproto, &ofproto->backer->rt_support); udpif_flush(ofproto->backer->udpif); @@ -6777,7 +6793,8 @@ ofproto_unixctl_init(void) unixctl_command_register("dpif/dump-flows", "[-m] [--names | --no-names] bridge", 1, INT_MAX, ofproto_unixctl_dpif_dump_flows, NULL); - unixctl_command_register("dpif/set-dp-features", "bridge", 1, 3 , + unixctl_command_register("dpif/set-dp-features", + "[--force] bridge [feature] [value]", 1, 4 , ofproto_unixctl_dpif_set_dp_features, NULL); } From patchwork Thu Jul 4 07:52:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956703 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=g7z+aL0s; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (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 4WF85l38n3z1xpP for ; Thu, 4 Jul 2024 17:53:15 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 61A8B40921; Thu, 4 Jul 2024 07:53:12 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id x_McTe_i0QRF; Thu, 4 Jul 2024 07:53:10 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 0F43440983 Authentication-Results: smtp2.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=g7z+aL0s Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id 0F43440983; Thu, 4 Jul 2024 07:53:10 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id D2F55C0A9A; Thu, 4 Jul 2024 07:53:09 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id C7670C0A9A for ; Thu, 4 Jul 2024 07:53:05 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id A5A238479C for ; Thu, 4 Jul 2024 07:53:05 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id sSyYiPAhmThV for ; Thu, 4 Jul 2024 07:53:04 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org 624278479B Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 624278479B Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=g7z+aL0s Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id 624278479B for ; Thu, 4 Jul 2024 07:53:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079583; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9Xi9Zs4cQqn9ew95L5J+TuEc6uYq9mNPissujor8aPU=; b=g7z+aL0soHVb0EeC/pmRhaq0UuH2B5OAexw+OimVjYtltF/z1kVCrAl3ChFwYwtCL0ssM5 /QBpvDO1qSbF3JKhzVIbbY2eDmtDKQdHd9EbwD3usA5FAzyGYiZ8lMOlsXFqiZ4s81yNEb zxnANiy1bPT3KjwHpPsXhsWCNT+O/OE= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-458-1lE06fBdOc66rk5G6edbdA-1; Thu, 04 Jul 2024 03:53:02 -0400 X-MC-Unique: 1lE06fBdOc66rk5G6edbdA-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2ED83196CE02 for ; Thu, 4 Jul 2024 07:53:01 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 058EA1956046; Thu, 4 Jul 2024 07:52:59 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:43 +0200 Message-ID: <20240704075255.140530-3-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 02/13] odp-util: Add support OVS_ACTION_ATTR_PSAMPLE. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Add support for parsing and formatting the new action. Also, flag OVS_ACTION_ATTR_SAMPLE as requiring datapath assistance if it contains a nested OVS_ACTION_ATTR_PSAMPLE. The reason is that the sampling rate form the parent "sample" is made available to the nested "psample" by the kernel. Signed-off-by: Adrian Moreno --- include/linux/openvswitch.h | 28 +++++++++++ lib/dpif-netdev.c | 1 + lib/dpif.c | 1 + lib/odp-execute.c | 25 +++++++++- lib/odp-util.c | 93 ++++++++++++++++++++++++++++++++++++ lib/odp-util.h | 3 ++ ofproto/ofproto-dpif-ipfix.c | 1 + ofproto/ofproto-dpif-sflow.c | 1 + python/ovs/flow/odp.py | 8 ++++ tests/odp.at | 16 +++++++ 10 files changed, 176 insertions(+), 1 deletion(-) diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h index d9fb991ef..0023b65fb 100644 --- a/include/linux/openvswitch.h +++ b/include/linux/openvswitch.h @@ -992,6 +992,31 @@ struct check_pkt_len_arg { }; #endif +#define OVS_PSAMPLE_COOKIE_MAX_SIZE 16 +/** + * enum ovs_pample_attr - Attributes for %OVS_ACTION_ATTR_PSAMPLE + * action. + * + * @OVS_PSAMPLE_ATTR_GROUP: 32-bit number to identify the source of the + * sample. + * @OVS_PSAMPLE_ATTR_COOKIE: An optional variable-length binary cookie that + * contains user-defined metadata. The maximum length is + * OVS_PSAMPLE_COOKIE_MAX_SIZE bytes. + * + * Sends the packet to the psample multicast group with the specified group and + * cookie. It is possible to combine this action with the + * %OVS_ACTION_ATTR_TRUNC action to limit the size of the sample. + */ +enum ovs_psample_attr { + OVS_PSAMPLE_ATTR_GROUP = 1, /* u32 number. */ + OVS_PSAMPLE_ATTR_COOKIE, /* Optional, user specified cookie. */ + + /* private: */ + __OVS_PSAMPLE_ATTR_MAX +}; + +#define OVS_PSAMPLE_ATTR_MAX (__OVS_PSAMPLE_ATTR_MAX - 1) + /** * enum ovs_action_attr - Action types. * @@ -1056,6 +1081,8 @@ struct check_pkt_len_arg { * of l3 tunnel flag in the tun_flags field of OVS_ACTION_ATTR_ADD_MPLS * argument. * @OVS_ACTION_ATTR_DROP: Explicit drop action. + * @OVS_ACTION_ATTR_PSAMPLE: Send a sample of the packet to external observers + * via psample. */ enum ovs_action_attr { @@ -1087,6 +1114,7 @@ enum ovs_action_attr { OVS_ACTION_ATTR_ADD_MPLS, /* struct ovs_action_add_mpls. */ OVS_ACTION_ATTR_DEC_TTL, /* Nested OVS_DEC_TTL_ATTR_*. */ OVS_ACTION_ATTR_DROP, /* u32 xlate_error. */ + OVS_ACTION_ATTR_PSAMPLE, /* Nested OVS_PSAMPLE_ATTR_*. */ #ifndef __KERNEL__ OVS_ACTION_ATTR_TUNNEL_PUSH, /* struct ovs_action_push_tnl*/ diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index c7f9e1490..f0594e5f5 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -9519,6 +9519,7 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_, case OVS_ACTION_ATTR_DROP: case OVS_ACTION_ATTR_ADD_MPLS: case OVS_ACTION_ATTR_DEC_TTL: + case OVS_ACTION_ATTR_PSAMPLE: case __OVS_ACTION_ATTR_MAX: OVS_NOT_REACHED(); } diff --git a/lib/dpif.c b/lib/dpif.c index 23eb18495..71728badc 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1192,6 +1192,7 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet_batch *packets_, case OVS_ACTION_ATTR_TUNNEL_PUSH: case OVS_ACTION_ATTR_TUNNEL_POP: case OVS_ACTION_ATTR_USERSPACE: + case OVS_ACTION_ATTR_PSAMPLE: case OVS_ACTION_ATTR_RECIRC: { struct dpif_execute execute; struct ofpbuf execute_actions; diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 081e4d432..15577d539 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -818,13 +818,13 @@ requires_datapath_assistance(const struct nlattr *a) case OVS_ACTION_ATTR_RECIRC: case OVS_ACTION_ATTR_CT: case OVS_ACTION_ATTR_METER: + case OVS_ACTION_ATTR_PSAMPLE: return true; case OVS_ACTION_ATTR_SET: case OVS_ACTION_ATTR_SET_MASKED: case OVS_ACTION_ATTR_PUSH_VLAN: case OVS_ACTION_ATTR_POP_VLAN: - case OVS_ACTION_ATTR_SAMPLE: case OVS_ACTION_ATTR_HASH: case OVS_ACTION_ATTR_PUSH_MPLS: case OVS_ACTION_ATTR_POP_MPLS: @@ -841,6 +841,28 @@ requires_datapath_assistance(const struct nlattr *a) case OVS_ACTION_ATTR_DROP: return false; + case OVS_ACTION_ATTR_SAMPLE: { + /* Nested "psample" actions rely on the datapath executing the + * parent "sample", storing the probability and making it available + * when the nested "psample" is run. */ + const struct nlattr *attr; + unsigned int left; + + NL_NESTED_FOR_EACH (attr, left, a) { + if (nl_attr_type(attr) == OVS_SAMPLE_ATTR_ACTIONS) { + const struct nlattr *act; + unsigned int act_left; + + NL_NESTED_FOR_EACH (act, act_left, attr) { + if (nl_attr_type(act) == OVS_ACTION_ATTR_PSAMPLE) { + return true; + } + } + } + } + return false; + } + case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: OVS_NOT_REACHED(); @@ -1229,6 +1251,7 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal, case OVS_ACTION_ATTR_CT: case OVS_ACTION_ATTR_UNSPEC: case OVS_ACTION_ATTR_DEC_TTL: + case OVS_ACTION_ATTR_PSAMPLE: case __OVS_ACTION_ATTR_MAX: /* The following actions are handled by the scalar implementation. */ case OVS_ACTION_ATTR_POP_VLAN: diff --git a/lib/odp-util.c b/lib/odp-util.c index 724e6f2bc..be9c8b449 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -145,6 +145,7 @@ odp_action_len(uint16_t type) case OVS_ACTION_ATTR_ADD_MPLS: return sizeof(struct ovs_action_add_mpls); case OVS_ACTION_ATTR_DEC_TTL: return ATTR_LEN_VARIABLE; case OVS_ACTION_ATTR_DROP: return sizeof(uint32_t); + case OVS_ACTION_ATTR_PSAMPLE: return ATTR_LEN_VARIABLE; case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: @@ -1150,6 +1151,30 @@ format_dec_ttl_action(struct ds *ds, const struct nlattr *attr, ds_put_format(ds, "))"); } +static void +format_odp_psample_action(struct ds *ds, const struct nlattr *attr) +{ + const struct nlattr *a; + unsigned int left; + + ds_put_cstr(ds, "psample("); + + NL_ATTR_FOR_EACH (a, left, + nl_attr_get(attr), nl_attr_get_size(attr)) { + switch (a->nla_type) { + case OVS_PSAMPLE_ATTR_GROUP: + ds_put_format(ds, "group=%"PRIu32",", nl_attr_get_u32(a)); + break; + case OVS_PSAMPLE_ATTR_COOKIE: + ds_put_cstr(ds, "cookie="); + ds_put_hex(ds, nl_attr_get(a), nl_attr_get_size(a)); + break; + } + } + ds_chomp(ds, ','); + ds_put_char(ds, ')'); +} + static void format_odp_action(struct ds *ds, const struct nlattr *a, const struct hmap *portno_names) @@ -1309,6 +1334,9 @@ format_odp_action(struct ds *ds, const struct nlattr *a, case OVS_ACTION_ATTR_DROP: ds_put_cstr(ds, "drop"); break; + case OVS_ACTION_ATTR_PSAMPLE: + format_odp_psample_action(ds, a); + break; case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: default: @@ -2358,6 +2386,50 @@ out: return ret; } +static int +parse_odp_psample_action(const char *s, struct ofpbuf *actions) +{ + char buf[2 * OVS_PSAMPLE_COOKIE_MAX_SIZE + 1]; + uint8_t cookie[OVS_PSAMPLE_COOKIE_MAX_SIZE]; + bool has_group = false; + size_t cookie_len = 0; + uint32_t group; + int n = 0; + + if (!ovs_scan_len(s, &n, "psample(")) { + return -EINVAL; + } + + while (s[n] != ')') { + n += strspn(s + n, delimiters); + + if (!has_group && ovs_scan_len(s, &n, "group=%"SCNi32, &group)) { + has_group = true; + continue; + } + + if (!cookie_len && + ovs_scan_len(s, &n, "cookie=0x%32[0-9a-fA-F]", buf) && n > 7) { + struct ofpbuf b; + + ofpbuf_use_stub(&b, cookie, OVS_PSAMPLE_COOKIE_MAX_SIZE); + ofpbuf_put_hex(&b, buf, &cookie_len); + ofpbuf_uninit(&b); + continue; + } + return -EINVAL; + } + n++; + + if (!has_group) { + return -EINVAL; + } + + odp_put_psample_action(actions, group, cookie_len ? cookie : NULL, + cookie_len); + return n; +} + static int parse_action_list(struct parse_odp_context *context, const char *s, struct ofpbuf *actions) @@ -2719,6 +2791,10 @@ parse_odp_action__(struct parse_odp_context *context, const char *s, } } + if (!strncmp(s, "psample(", 8)) { + return parse_odp_psample_action(s, actions); + } + { struct ovs_action_push_tnl data; int n; @@ -7828,6 +7904,23 @@ odp_put_tnl_push_action(struct ofpbuf *odp_actions, nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_TUNNEL_PUSH, data, size); } +void +odp_put_psample_action(struct ofpbuf *odp_actions, uint32_t group_id, + uint8_t *cookie, size_t cookie_len) +{ + size_t offset = nl_msg_start_nested_with_flag(odp_actions, + OVS_ACTION_ATTR_PSAMPLE); + + nl_msg_put_u32(odp_actions, OVS_PSAMPLE_ATTR_GROUP, group_id); + if (cookie && cookie_len) { + ovs_assert(cookie_len <= OVS_PSAMPLE_COOKIE_MAX_SIZE); + nl_msg_put_unspec(odp_actions, OVS_PSAMPLE_ATTR_COOKIE, cookie, + cookie_len); + } + + nl_msg_end_nested(odp_actions, offset); +} + /* The commit_odp_actions() function and its helpers. */ diff --git a/lib/odp-util.h b/lib/odp-util.h index 8c7baa680..e454dbfcd 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -376,6 +376,9 @@ void odp_put_pop_eth_action(struct ofpbuf *odp_actions); void odp_put_push_eth_action(struct ofpbuf *odp_actions, const struct eth_addr *eth_src, const struct eth_addr *eth_dst); +void odp_put_psample_action(struct ofpbuf *odp_actions, + uint32_t group_id, uint8_t *cookie, + size_t cookie_len); static inline void odp_decode_gbp_raw(uint32_t gbp_raw, ovs_be16 *id, diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c index cd65dae7e..15b656233 100644 --- a/ofproto/ofproto-dpif-ipfix.c +++ b/ofproto/ofproto-dpif-ipfix.c @@ -3136,6 +3136,7 @@ dpif_ipfix_read_actions(const struct flow *flow, case OVS_ACTION_ATTR_DROP: case OVS_ACTION_ATTR_ADD_MPLS: case OVS_ACTION_ATTR_DEC_TTL: + case OVS_ACTION_ATTR_PSAMPLE: case __OVS_ACTION_ATTR_MAX: default: break; diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index 80405b68a..fb12cf419 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -1237,6 +1237,7 @@ dpif_sflow_read_actions(const struct flow *flow, case OVS_ACTION_ATTR_DROP: case OVS_ACTION_ATTR_ADD_MPLS: case OVS_ACTION_ATTR_DEC_TTL: + case OVS_ACTION_ATTR_PSAMPLE: case __OVS_ACTION_ATTR_MAX: default: break; diff --git a/python/ovs/flow/odp.py b/python/ovs/flow/odp.py index a8f8c067a..572dbebe9 100644 --- a/python/ovs/flow/odp.py +++ b/python/ovs/flow/odp.py @@ -343,6 +343,14 @@ class ODPFlow(Flow): } ) ), + "psample": nested_kv_decoder( + KVDecoders( + { + "group": decode_int, + "cookie": decode_default, + } + ) + ) } _decoders["sample"] = nested_kv_decoder( diff --git a/tests/odp.at b/tests/odp.at index ba20604e4..402b2386d 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -393,6 +393,10 @@ check_pkt_len(size=200,gt(ct(nat)),le(drop)) check_pkt_len(size=200,gt(set(eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15))),le(set(eth(src=00:01:02:03:04:06,dst=10:11:12:13:14:16)))) lb_output(1) add_mpls(label=200,tc=7,ttl=64,bos=1,eth_type=0x8847) +psample(group=12,cookie=0xf1020304050607080910111213141516) +psample(group=12) +sample(sample=50.0%,actions(psample(group=12,cookie=0xf1020304))) +sample(sample=50.0%,actions(userspace(pid=42,userdata(0102030400000000)),psample(group=12))) ]) AT_CHECK_UNQUOTED([ovstest test-odp parse-actions < actions.txt], [0], [`cat actions.txt` @@ -406,11 +410,23 @@ AT_DATA([actions.txt], [dnl encap_nsh@:{@ tnl_push(tnl_port(6),header(size=94,type=112,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=43,tclass=0x0,hlimit=64),srv6(segments_left=2,segs(2001:cafe::90,2001:cafe::91))),out_port(1)) tnl_push(tnl_port(6),header(size=126,type=112,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=43,tclass=0x0,hlimit=64),srv6(segments_left=2,segs(2001:cafe::90,2001:cafe::91,2001:cafe::92,2001:cafe::93))),out_port(1)) +psample(group_id=12,cookie=0x0102030405060708090a0b0c0d0e0f0f0f) +psample(cookie=0x010203) +psample(group=12,cookie=0x010203,group=12) +psample(group=abc) +psample(group=12,cookie=wrong) +psample() ]) AT_CHECK_UNQUOTED([ovstest test-odp parse-actions < actions.txt], [0], [dnl odp_actions_from_string: error odp_actions_from_string: error odp_actions_from_string: error +odp_actions_from_string: error +odp_actions_from_string: error +odp_actions_from_string: error +odp_actions_from_string: error +odp_actions_from_string: error +odp_actions_from_string: error ]) AT_CLEANUP From patchwork Thu Jul 4 07:52:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956704 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Fa5a3b50; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (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 4WF85n4cl5z1xpP for ; Thu, 4 Jul 2024 17:53:17 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id B530C847CF; Thu, 4 Jul 2024 07:53:15 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id USRsLQXV2r0L; Thu, 4 Jul 2024 07:53:12 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org C93ED847A9 Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Fa5a3b50 Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTPS id C93ED847A9; Thu, 4 Jul 2024 07:53:11 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 47C2DC0A97; Thu, 4 Jul 2024 07:53:11 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 7188BC0A99 for ; Thu, 4 Jul 2024 07:53:07 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 4683760AD9 for ; Thu, 4 Jul 2024 07:53:07 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id eauzQWpIopMN for ; Thu, 4 Jul 2024 07:53:06 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp3.osuosl.org 4BF1360827 Authentication-Results: smtp3.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 4BF1360827 Authentication-Results: smtp3.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Fa5a3b50 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id 4BF1360827 for ; Thu, 4 Jul 2024 07:53:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079585; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=enPGRsOVsaG2m04psuP0DGJG3ALLgTKs9bBpOfpd8Is=; b=Fa5a3b50ph5eHW1dSR5P+z2MJxsnDKqVPCILJQEpGSYYaf/659A//CUkfCbIGBshYAIV51 7g4aZaHOdkSj5RtmRhE2skJnKrCinZoZaZ1XiaCQQhbwXdmsIgu3Wc6BlXdfPY0GTxeG4o Zy8epEQCv0SH78Rib9XPVghfRsy9nnk= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-427-lMXQ6opDMgODX6Reamshog-1; Thu, 04 Jul 2024 03:53:03 -0400 X-MC-Unique: lMXQ6opDMgODX6Reamshog-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BEE8A1955F40 for ; Thu, 4 Jul 2024 07:53:02 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 75C5F1956046; Thu, 4 Jul 2024 07:53:01 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:44 +0200 Message-ID: <20240704075255.140530-4-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 03/13] ofproto_dpif: Check for psample support. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Only kernel datapath supports this action so add a function in dpif.c that checks for that. Signed-off-by: Adrian Moreno --- lib/dpif.c | 7 +++++++ lib/dpif.h | 1 + ofproto/ofproto-dpif.c | 43 ++++++++++++++++++++++++++++++++++++++++++ ofproto/ofproto-dpif.h | 7 ++++++- 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/lib/dpif.c b/lib/dpif.c index 71728badc..0a964ba89 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1953,6 +1953,13 @@ dpif_supports_lb_output_action(const struct dpif *dpif) return dpif_is_netdev(dpif); } +bool +dpif_may_support_psample(const struct dpif *dpif) +{ + /* Userspace datapath does not support this action. */ + return !dpif_is_netdev(dpif); +} + /* Meters */ void dpif_meter_get_features(const struct dpif *dpif, diff --git a/lib/dpif.h b/lib/dpif.h index a764e8a59..6bef7d5b3 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -941,6 +941,7 @@ int dpif_get_pmds_for_port(const struct dpif * dpif, odp_port_t port_no, char *dpif_get_dp_version(const struct dpif *); bool dpif_supports_tnl_push_pop(const struct dpif *); bool dpif_may_support_explicit_drop_action(const struct dpif *); +bool dpif_may_support_psample(const struct dpif *); bool dpif_synced_dp_layers(struct dpif *); /* Log functions. */ diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 4712d10a8..94c84d697 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -873,6 +873,12 @@ ovs_lb_output_action_supported(struct ofproto_dpif *ofproto) return ofproto->backer->rt_support.lb_output_action; } +bool +ovs_psample_supported(struct ofproto_dpif *ofproto) +{ + return ofproto->backer->rt_support.psample; +} + /* Tests whether 'backer''s datapath supports recirculation. Only newer * datapaths support OVS_KEY_ATTR_RECIRC_ID in keys. We need to disable some * features on older datapaths that don't support this feature. @@ -1609,6 +1615,42 @@ check_add_mpls(struct dpif_backer *backer) return supported; } +/* Tests whether 'backer''s datapath supports the OVS_ACTION_ATTR_PSAMPLE + * action. */ +static bool +check_psample(struct dpif_backer *backer) +{ + uint8_t cookie[OVS_PSAMPLE_COOKIE_MAX_SIZE]; + struct odputil_keybuf keybuf; + struct ofpbuf actions; + struct ofpbuf key; + struct flow flow; + bool supported; + + struct odp_flow_key_parms odp_parms = { + .flow = &flow, + .probe = true, + }; + + memset(&flow, 0, sizeof flow); + ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); + odp_flow_key_from_flow(&odp_parms, &key); + ofpbuf_init(&actions, 64); + + /* Generate a random max-size cookie. */ + random_bytes(cookie, sizeof(cookie)); + + odp_put_psample_action(&actions, 10, cookie, sizeof cookie); + + supported = dpif_may_support_psample(backer->dpif) && + dpif_probe_feature(backer->dpif, "psample", &key, &actions, NULL); + + ofpbuf_uninit(&actions); + VLOG_INFO("%s: Datapath %s psample", dpif_name(backer->dpif), + supported ? "supports" : "does not support"); + return supported; +} + #define CHECK_FEATURE__(NAME, SUPPORT, FIELD, VALUE, ETHTYPE) \ static bool \ check_##NAME(struct dpif_backer *backer) \ @@ -1698,6 +1740,7 @@ check_support(struct dpif_backer *backer) dpif_supports_lb_output_action(backer->dpif); backer->rt_support.ct_zero_snat = dpif_supports_ct_zero_snat(backer); backer->rt_support.add_mpls = check_add_mpls(backer); + backer->rt_support.psample = check_psample(backer); /* Flow fields. */ backer->rt_support.odp.ct_state = check_ct_state(backer); diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index d33f73df8..bc7a19dab 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -213,7 +213,10 @@ struct group_dpif *group_dpif_lookup(struct ofproto_dpif *, DPIF_SUPPORT_FIELD(bool, ct_zero_snat, "Conntrack all-zero IP SNAT") \ \ /* True if the datapath supports add_mpls action. */ \ - DPIF_SUPPORT_FIELD(bool, add_mpls, "MPLS Label add") + DPIF_SUPPORT_FIELD(bool, add_mpls, "MPLS Label add") \ + \ + /* True if the datapath supports psample action. */ \ + DPIF_SUPPORT_FIELD(bool, psample, "psample") /* Stores the various features which the corresponding backer supports. */ @@ -412,4 +415,6 @@ bool ofproto_dpif_ct_zone_timeout_policy_get_name( bool ovs_explicit_drop_action_supported(struct ofproto_dpif *); +bool ovs_psample_supported(struct ofproto_dpif *); + #endif /* ofproto-dpif.h */ From patchwork Thu Jul 4 07:52:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956705 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SdsVNvzI; 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 4WF85q0LJcz1xpP for ; Thu, 4 Jul 2024 17:53:18 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 7CA2140C8B; Thu, 4 Jul 2024 07:53:16 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id I_NA_XyolB47; Thu, 4 Jul 2024 07:53:14 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org EB2D540C97 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SdsVNvzI Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id EB2D540C97; Thu, 4 Jul 2024 07:53:13 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id A96A0C0A98; Thu, 4 Jul 2024 07:53:13 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id A283DC0A99 for ; Thu, 4 Jul 2024 07:53:09 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 79A1260B25 for ; Thu, 4 Jul 2024 07:53:09 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id ARBFCKm5EhdM for ; Thu, 4 Jul 2024 07:53:07 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp3.osuosl.org 8EDDC60AD9 Authentication-Results: smtp3.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 8EDDC60AD9 Authentication-Results: smtp3.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SdsVNvzI Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id 8EDDC60AD9 for ; Thu, 4 Jul 2024 07:53:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079586; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=67/uKx5OQMmP10Ap6vziBmXO4uQowV6WNK7LbUCM318=; b=SdsVNvzIVgbE586ltNiuJ03Crconmcw6MOvdIRO03VgXNuQvfZ5KBj/n6wqqB2XeppvPQd 5SdnUglkaywXx8wGIbhGpqi+t8+D2v9IRlOMWIlwf6qBf/2aH+OJ/Ikl9qoJp+BtuqqCLL Pb7zIUhbWAYhmsTCnfokwaTDnG0xVMM= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-647-rj4HbMT-M_6UWlHXXGlE3Q-1; Thu, 04 Jul 2024 03:53:05 -0400 X-MC-Unique: rj4HbMT-M_6UWlHXXGlE3Q-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3D46E195608A for ; Thu, 4 Jul 2024 07:53:04 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0B06C1956046; Thu, 4 Jul 2024 07:53:02 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:45 +0200 Message-ID: <20240704075255.140530-5-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 04/13] ofproto: Add ofproto-dpif-lsample. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Add a new resource in ofproto-dpif and the corresponding API in ofproto_provider.h to represent and local sampling configuration. Signed-off-by: Adrian Moreno --- ofproto/automake.mk | 2 + ofproto/ofproto-dpif-lsample.c | 187 +++++++++++++++++++++++++++++++++ ofproto/ofproto-dpif-lsample.h | 36 +++++++ ofproto/ofproto-dpif.c | 38 +++++++ ofproto/ofproto-dpif.h | 1 + ofproto/ofproto-provider.h | 9 ++ ofproto/ofproto.c | 12 +++ ofproto/ofproto.h | 8 ++ 8 files changed, 293 insertions(+) create mode 100644 ofproto/ofproto-dpif-lsample.c create mode 100644 ofproto/ofproto-dpif-lsample.h diff --git a/ofproto/automake.mk b/ofproto/automake.mk index 7c08b563b..cb1361b8a 100644 --- a/ofproto/automake.mk +++ b/ofproto/automake.mk @@ -30,6 +30,8 @@ ofproto_libofproto_la_SOURCES = \ ofproto/ofproto-dpif.h \ ofproto/ofproto-dpif-ipfix.c \ ofproto/ofproto-dpif-ipfix.h \ + ofproto/ofproto-dpif-lsample.c \ + ofproto/ofproto-dpif-lsample.h \ ofproto/ofproto-dpif-mirror.c \ ofproto/ofproto-dpif-mirror.h \ ofproto/ofproto-dpif-monitor.c \ diff --git a/ofproto/ofproto-dpif-lsample.c b/ofproto/ofproto-dpif-lsample.c new file mode 100644 index 000000000..d675a116f --- /dev/null +++ b/ofproto/ofproto-dpif-lsample.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ofproto-dpif-lsample.h" + +#include "cmap.h" +#include "hash.h" +#include "ofproto.h" +#include "openvswitch/thread.h" + +/* Dpif local sampling. + * + * Thread safety: dpif_lsample allows lockless concurrent reads of local + * sampling exporters as long as the following restrictions are met: + * 1) While the last reference is being dropped, i.e: a thread is calling + * "dpif_lsample_unref" on the last reference, other threads cannot call + * "dpif_lsample_ref". + * 2) Threads do not quiese while holding references to internal + * lsample_exporter objects. + */ + +struct dpif_lsample { + struct cmap exporters; /* Contains lsample_exporter_node instances + indexed by collector_set_id. */ + struct ovs_mutex mutex; /* Protects concurrent insertion/deletion + * of exporters. */ + + struct ovs_refcount ref_cnt; /* Controls references to this instance. */ +}; + +struct lsample_exporter { + struct ofproto_lsample_options options; +}; + +struct lsample_exporter_node { + struct cmap_node node; /* In dpif_lsample->exporters. */ + struct lsample_exporter exporter; +}; + +static void +dpif_lsample_delete_exporter(struct dpif_lsample *lsample, + struct lsample_exporter_node *node) +{ + ovs_mutex_lock(&lsample->mutex); + cmap_remove(&lsample->exporters, &node->node, + hash_int(node->exporter.options.collector_set_id, 0)); + ovs_mutex_unlock(&lsample->mutex); + + ovsrcu_postpone(free, node); +} + +/* Adds an exporter with the provided options which are copied. */ +static struct lsample_exporter_node * +dpif_lsample_add_exporter(struct dpif_lsample *lsample, + const struct ofproto_lsample_options *options) +{ + struct lsample_exporter_node *node; + + node = xzalloc(sizeof *node); + node->exporter.options = *options; + + ovs_mutex_lock(&lsample->mutex); + cmap_insert(&lsample->exporters, &node->node, + hash_int(options->collector_set_id, 0)); + ovs_mutex_unlock(&lsample->mutex); + + return node; +} + +static struct lsample_exporter_node * +dpif_lsample_find_exporter_node(const struct dpif_lsample *lsample, + const uint32_t collector_set_id) +{ + struct lsample_exporter_node *node; + + CMAP_FOR_EACH_WITH_HASH (node, node, + hash_int(collector_set_id, 0), + &lsample->exporters) { + if (node->exporter.options.collector_set_id == collector_set_id) { + return node; + } + } + return NULL; +} + +/* Sets the lsample configuration and returns true if the configuration + * has changed. */ +bool +dpif_lsample_set_options(struct dpif_lsample *lsample, + const struct ofproto_lsample_options *options, + size_t n_options) +{ + const struct ofproto_lsample_options *opt; + struct lsample_exporter_node *node; + bool changed = false; + int i; + + for (i = 0; i < n_options; i++) { + opt = &options[i]; + node = dpif_lsample_find_exporter_node(lsample, + opt->collector_set_id); + if (!node) { + dpif_lsample_add_exporter(lsample, opt); + changed = true; + } else if (memcmp(&node->exporter.options, opt, sizeof(*opt))) { + dpif_lsample_delete_exporter(lsample, node); + dpif_lsample_add_exporter(lsample, opt); + changed = true; + } + } + + /* Delete exporters that have been removed. */ + CMAP_FOR_EACH (node, node, &lsample->exporters) { + for (i = 0; i < n_options; i++) { + if (node->exporter.options.collector_set_id + == options[i].collector_set_id) { + break; + } + } + if (i == n_options) { + dpif_lsample_delete_exporter(lsample, node); + changed = true; + } + } + + return changed; +} + +struct dpif_lsample * +dpif_lsample_create(void) +{ + struct dpif_lsample *lsample; + + lsample = xzalloc(sizeof *lsample); + cmap_init(&lsample->exporters); + ovs_mutex_init(&lsample->mutex); + ovs_refcount_init(&lsample->ref_cnt); + + return lsample; +} + +static void +dpif_lsample_destroy(struct dpif_lsample *lsample) +{ + if (lsample) { + struct lsample_exporter_node *node; + + CMAP_FOR_EACH (node, node, &lsample->exporters) { + dpif_lsample_delete_exporter(lsample, node); + } + cmap_destroy(&lsample->exporters); + free(lsample); + } +} + +struct dpif_lsample * +dpif_lsample_ref(const struct dpif_lsample *lsample_) +{ + struct dpif_lsample *lsample = CONST_CAST(struct dpif_lsample *, lsample_); + + if (lsample) { + ovs_refcount_ref(&lsample->ref_cnt); + } + return lsample; +} + +void +dpif_lsample_unref(struct dpif_lsample *lsample) +{ + if (lsample && ovs_refcount_unref_relaxed(&lsample->ref_cnt) == 1) { + dpif_lsample_destroy(lsample); + } +} diff --git a/ofproto/ofproto-dpif-lsample.h b/ofproto/ofproto-dpif-lsample.h new file mode 100644 index 000000000..bee36c9c5 --- /dev/null +++ b/ofproto/ofproto-dpif-lsample.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OFPROTO_DPIF_LSAMPLE_H +#define OFPROTO_DPIF_LSAMPLE_H 1 + +#include +#include + +struct dpif_lsample; +struct ofproto_lsample_options; + +struct dpif_lsample *dpif_lsample_create(void); + +void dpif_lsample_unref(struct dpif_lsample *); + +struct dpif_lsample *dpif_lsample_ref(const struct dpif_lsample *); + +bool dpif_lsample_set_options(struct dpif_lsample *, + const struct ofproto_lsample_options *, + size_t n_opts); + +#endif /* OFPROTO_DPIF_LSAMPLE_H */ diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 94c84d697..56830c630 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -49,6 +49,7 @@ #include "ofproto-dpif-sflow.h" #include "ofproto-dpif-trace.h" #include "ofproto-dpif-upcall.h" +#include "ofproto-dpif-lsample.h" #include "ofproto-dpif-xlate.h" #include "ofproto-dpif-xlate-cache.h" #include "openvswitch/ofp-actions.h" @@ -1954,6 +1955,7 @@ destruct(struct ofproto *ofproto_, bool del) netflow_unref(ofproto->netflow); dpif_sflow_unref(ofproto->sflow); dpif_ipfix_unref(ofproto->ipfix); + dpif_lsample_unref(ofproto->lsample); hmap_destroy(&ofproto->bundles); mac_learning_unref(ofproto->ml); mcast_snooping_unref(ofproto->ms); @@ -2513,6 +2515,41 @@ get_ipfix_stats(const struct ofproto *ofproto_, return dpif_ipfix_get_stats(di, bridge_ipfix, replies); } +static int +set_local_sample(struct ofproto *ofproto_, + const struct ofproto_lsample_options *options, + size_t n_opts) +{ + struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); + struct dpif_lsample *lsample = ofproto->lsample; + bool changed = false; + + if (!ofproto->backer->rt_support.psample) { + return ENOTSUP; + } + + if (n_opts && !lsample) { + lsample = ofproto->lsample = dpif_lsample_create(); + changed = true; + } + + if (lsample) { + if (!n_opts) { + dpif_lsample_unref(lsample); + lsample = ofproto->lsample = NULL; + changed = true; + } else { + changed |= dpif_lsample_set_options(lsample, options, n_opts); + } + } + + if (changed) { + ofproto->backer->need_revalidate = REV_RECONFIGURE; + } + + return 0; +} + static int set_cfm(struct ofport *ofport_, const struct cfm_settings *s) { @@ -7100,6 +7137,7 @@ const struct ofproto_class ofproto_dpif_class = { get_netflow_ids, set_sflow, set_ipfix, + set_local_sample, get_ipfix_stats, set_cfm, cfm_status_changed, diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index bc7a19dab..420c350fd 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -331,6 +331,7 @@ struct ofproto_dpif { struct netflow *netflow; struct dpif_sflow *sflow; struct dpif_ipfix *ipfix; + struct dpif_lsample *lsample; struct hmap bundles; /* Contains "struct ofbundle"s. */ struct mac_learning *ml; struct mcast_snooping *ms; diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 83c509fcf..02e6710d9 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1479,6 +1479,15 @@ struct ofproto_class { const struct ofproto_ipfix_flow_exporter_options *flow_exporters_options, size_t n_flow_exporters_options); + /* Configures local sampling on 'ofproto' according to the options array + * of 'options' which contains 'n_options' elements. + * + * EOPNOTSUPP as a return value indicates that 'ofproto' does not support + * local sampling. */ + int (*set_local_sample)(struct ofproto *ofproto, + const struct ofproto_lsample_options *options, + size_t n_options); + /* Gets IPFIX stats on 'ofproto' according to the exporter of birdge * IPFIX or flow-based IPFIX. * diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 21c6a1d82..2a1db8a0a 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1000,6 +1000,18 @@ ofproto_get_datapath_cap(const char *datapath_type, struct smap *dp_cap) } } +int ofproto_set_local_sample(struct ofproto *ofproto, + const struct ofproto_lsample_options *options, + size_t n_options) +{ + if (ofproto->ofproto_class->set_local_sample) { + return ofproto->ofproto_class->set_local_sample(ofproto, options, + n_options); + } else { + return ENOTSUP; + } +} + /* Connection tracking configuration. */ void ofproto_ct_set_zone_timeout_policy(const char *datapath_type, uint16_t zone_id, diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 1c07df275..fded3a3db 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -103,6 +103,11 @@ struct ofproto_ipfix_flow_exporter_options { char *virtual_obs_id; }; +struct ofproto_lsample_options { + uint32_t collector_set_id; + uint32_t group_id; +}; + struct ofproto_rstp_status { bool enabled; /* If false, ignore other members. */ rstp_identifier root_id; @@ -390,6 +395,9 @@ void ofproto_ct_zone_limit_protection_update(const char *datapath_type, bool protected); void ofproto_get_datapath_cap(const char *datapath_type, struct smap *dp_cap); +int ofproto_set_local_sample(struct ofproto *ofproto, + const struct ofproto_lsample_options *, + size_t n_options); /* Configuration of ports. */ void ofproto_port_unregister(struct ofproto *, ofp_port_t ofp_port); From patchwork Thu Jul 4 07:52:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956706 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SdF1k5rR; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::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 4WF85t0JVDz1xpP for ; Thu, 4 Jul 2024 17:53:22 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 506F4410BE; Thu, 4 Jul 2024 07:53:19 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id XqXBHiZ-i6Ly; Thu, 4 Jul 2024 07:53:15 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 537C4409EE Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SdF1k5rR Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 537C4409EE; Thu, 4 Jul 2024 07:53:15 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0D3BBC0A98; Thu, 4 Jul 2024 07:53:15 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 18A63C0A9A for ; Thu, 4 Jul 2024 07:53:11 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 58A4260796 for ; Thu, 4 Jul 2024 07:53:10 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 3RSrq7sZrCZr for ; Thu, 4 Jul 2024 07:53:09 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp3.osuosl.org D785660B1B Authentication-Results: smtp3.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org D785660B1B Authentication-Results: smtp3.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SdF1k5rR Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id D785660B1B for ; Thu, 4 Jul 2024 07:53:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079587; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ojBqJlGVFF6wTykVyHT1mQsvGqOVnqRrdzaom8FPAZw=; b=SdF1k5rRrXGYi2COxa+3CgAJl9C59T3ldsvaO27rocUMMz+ZZQZTBM9SyfFSNoA54lzCUb 6vZXIeYPLBLU0H4PyUHYeadcRTdnQ8szfvx/hKibXrS3wH/W7JVTdRgPV3umjPrvyzcapP 3lIxp6T6GgLfZGvvYtdfmt4hFfdYESU= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-135-xMvbH5zqMf6MZ5U-lWlCAA-1; Thu, 04 Jul 2024 03:53:06 -0400 X-MC-Unique: xMvbH5zqMf6MZ5U-lWlCAA-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 89A1F19560AA for ; Thu, 4 Jul 2024 07:53:05 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7B40C1955F65; Thu, 4 Jul 2024 07:53:04 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:46 +0200 Message-ID: <20240704075255.140530-6-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 05/13] vswitchd: Add local sampling to vswitchd schema. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Add as new column in the Flow_Sample_Collector_Set table named "local_group_id" which enables this feature. Signed-off-by: Adrian Moreno --- NEWS | 4 ++ vswitchd/bridge.c | 78 +++++++++++++++++++++++++++++++++++--- vswitchd/vswitch.ovsschema | 9 ++++- vswitchd/vswitch.xml | 40 +++++++++++++++++-- 4 files changed, 120 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index e0359b759..15faf9fc3 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,10 @@ Post-v3.3.0 per interface 'options:dpdk-lsc-interrupt' to 'false'. - Python: * Added custom transaction support to the Idl via add_op(). + - Local sampling is introduced. It reuses the OpenFlow sample action and + allows samples to be emitted locally (instead of via IPFIX) in a + datapath-specific manner. The Linux kernel datapath is the first to + support this feature by using the new datapath "psample" action. v3.3.0 - 16 Feb 2024 diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 95a65fcdc..b7db681f3 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -288,6 +288,7 @@ static void bridge_configure_mac_table(struct bridge *); static void bridge_configure_mcast_snooping(struct bridge *); static void bridge_configure_sflow(struct bridge *, int *sflow_bridge_number); static void bridge_configure_ipfix(struct bridge *); +static void bridge_configure_lsample(struct bridge *); static void bridge_configure_spanning_tree(struct bridge *); static void bridge_configure_tables(struct bridge *); static void bridge_configure_dp_desc(struct bridge *); @@ -989,6 +990,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) bridge_configure_netflow(br); bridge_configure_sflow(br, &sflow_bridge_number); bridge_configure_ipfix(br); + bridge_configure_lsample(br); bridge_configure_spanning_tree(br); bridge_configure_tables(br); bridge_configure_dp_desc(br); @@ -1537,10 +1539,11 @@ ovsrec_ipfix_is_valid(const struct ovsrec_ipfix *ipfix) return ipfix && ipfix->n_targets > 0; } -/* Returns whether a Flow_Sample_Collector_Set row is valid. */ +/* Returns whether a Flow_Sample_Collector_Set row contains a valid IPFIX + * configuration. */ static bool -ovsrec_fscs_is_valid(const struct ovsrec_flow_sample_collector_set *fscs, - const struct bridge *br) +ovsrec_fscs_is_valid_ipfix(const struct ovsrec_flow_sample_collector_set *fscs, + const struct bridge *br) { return ovsrec_ipfix_is_valid(fscs->ipfix) && fscs->bridge == br->cfg; } @@ -1558,7 +1561,7 @@ bridge_configure_ipfix(struct bridge *br) const char *virtual_obs_id; OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) { - if (ovsrec_fscs_is_valid(fe_cfg, br)) { + if (ovsrec_fscs_is_valid_ipfix(fe_cfg, br)) { n_fe_opts++; } } @@ -1621,7 +1624,7 @@ bridge_configure_ipfix(struct bridge *br) fe_opts = xcalloc(n_fe_opts, sizeof *fe_opts); opts = fe_opts; OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) { - if (ovsrec_fscs_is_valid(fe_cfg, br)) { + if (ovsrec_fscs_is_valid_ipfix(fe_cfg, br)) { opts->collector_set_id = fe_cfg->id; sset_init(&opts->targets); sset_add_array(&opts->targets, fe_cfg->ipfix->targets, @@ -1667,6 +1670,71 @@ bridge_configure_ipfix(struct bridge *br) } } +/* Returns whether a Flow_Sample_Collector_Set row contains a valid local + * sampling configuration. */ +static bool +ovsrec_fscs_is_valid_local(const struct ovsrec_flow_sample_collector_set *fscs, + const struct bridge *br) +{ + return fscs->local_group_id && fscs->n_local_group_id == 1 && + fscs->bridge == br->cfg; +} + +/* Set local sample configuration on 'br'. */ +static void +bridge_configure_lsample(struct bridge *br) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + const struct ovsrec_flow_sample_collector_set *fscs; + struct ofproto_lsample_options *opts_array, *opts; + size_t n_opts = 0; + int ret; + + /* Iterate the Flow_Sample_Collector_Set table twice. + * First to get the number of valid configuration entries, then to process + * each of them and build an array of options. */ + OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH (fscs, idl) { + if (ovsrec_fscs_is_valid_local(fscs, br)) { + n_opts ++; + } + } + + if (n_opts == 0) { + ofproto_set_local_sample(br->ofproto, NULL, 0); + return; + } + + opts_array = xcalloc(n_opts, sizeof *opts_array); + opts = opts_array; + + OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH (fscs, idl) { + if (!ovsrec_fscs_is_valid_local(fscs, br)) { + continue; + } + opts->collector_set_id = fscs->id; + opts->group_id = *fscs->local_group_id; + opts++; + } + + ret = ofproto_set_local_sample(br->ofproto, opts_array, n_opts); + + if (ret == ENOTSUP) { + if (n_opts) { + VLOG_WARN_RL(&rl, + "bridge %s: ignoring local sampling configuration: " + "not supported by this datapath", + br->name); + } + } else if (ret) { + VLOG_ERR_RL(&rl, "bridge %s: error configuring local sampling: %s", + br->name, ovs_strerror(ret)); + } + + if (n_opts > 0) { + free(opts_array); + } +} + static void port_configure_stp(const struct ofproto *ofproto, struct port *port, struct ofproto_port_stp_settings *port_s, diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index e2d5e2e85..95018d107 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", - "version": "8.5.0", - "cksum": "4040946650 27557", + "version": "8.6.0", + "cksum": "1543805939 27765", "tables": { "Open_vSwitch": { "columns": { @@ -562,6 +562,11 @@ "type": {"key": {"type": "uuid", "refTable": "IPFIX"}, "min": 0, "max": 1}}, + "local_group_id": { + "type": {"key": {"type": "integer", + "minInteger": 0, + "maxInteger": 4294967295}, + "min": 0, "max": 1}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index e3afb78a4..a162bfc5e 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -7008,10 +7008,37 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \

- A set of IPFIX collectors of packet samples generated by OpenFlow - sample actions. This table is used only for IPFIX - flow-based sampling, not for per-bridge sampling (see the table for a description of the two forms). + A set of IPFIX or local sampling collectors of packet samples generated + by OpenFlow sample actions. +

+ +

+ If the column ipfix contains a reference to a + valid IPFIX entry, samples will be emitted via IPFIX. This mechanism + is known as flow-based IPFIX sampling, as opposed to bridge-based + sampling (see the table for a description of the + two forms). +

+ +

+ If the column local_group_id contains an integer and the + running datapath supports local sample emission, packets will be sent + to some local sample collector. Samples will contain the group number + specified by local_group_id which helps identify their + source as well as a 64-bit cookie result from the concatenation of the + observation_domain_id an the observation_point_id in network order. + + The way the sample is emitted and made available for local collectors + is datapath-specific. + + Currently only Linux kernel datapath supports local sampling which is + implemented by sending the packet to the psample netlink + multicast group. +

+ +

+ Note both local_group_id and ipfix can be + configured simultaneously.

@@ -7030,6 +7057,11 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \ record per sampled packet to. + + Configuration of the sample group id to be used in local sampling. + + The overall purpose of these columns is described under Common Columns at the beginning of this document. From patchwork Thu Jul 4 07:52:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956709 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SBsxvnzm; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (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 4WF8696vQqz1xpP for ; Thu, 4 Jul 2024 17:53:37 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 3C566847B8; Thu, 4 Jul 2024 07:53:36 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id UqErvoE9ZRrE; Thu, 4 Jul 2024 07:53:27 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 0FC44847F7 Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SBsxvnzm Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 0FC44847F7; Thu, 4 Jul 2024 07:53:21 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 91B5EC0A98; Thu, 4 Jul 2024 07:53:21 +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 147AEC0A96 for ; Thu, 4 Jul 2024 07:53:20 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 46FCD847C5 for ; Thu, 4 Jul 2024 07:53:16 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id auYLM6GW1Drr for ; Thu, 4 Jul 2024 07:53:11 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org 36D55847A2 Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 36D55847A2 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id 36D55847A2 for ; Thu, 4 Jul 2024 07:53:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079590; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LDV/WpranTAxAhGQkne0Rci1bM60xqRS3rxeoDQmW0g=; b=SBsxvnzmNIGlK+F7V4DrVuVgWzOCp594UrQqIe6HetRkyZ6Zw2JA7kpBcC0IocuFiArRrs kJWACXDCbpAH8hNHDqhg0gwzSXShc1IG06j9+rPscCfq+cpCvBy5ljVOG5ef37CswTVZX0 ldR6uGaEq8keMwRpWsOznxjV2qMIamw= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-496-LTC17Y1lMZ-Z4jLF6vAO3g-1; Thu, 04 Jul 2024 03:53:08 -0400 X-MC-Unique: LTC17Y1lMZ-Z4jLF6vAO3g-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 818E019560AA for ; Thu, 4 Jul 2024 07:53:07 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 001201955F68; Thu, 4 Jul 2024 07:53:05 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:47 +0200 Message-ID: <20240704075255.140530-7-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 06/13] ofproto-dpif-xlate: Use psample for local sample. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Use the newly added psample action to implement OpenFlow sample() actions with local sampling configuration if possible. A bit of refactoring in compose_sample_actions arguments helps make it a bit more readable. Signed-off-by: Adrian Moreno --- ofproto/ofproto-dpif-lsample.c | 16 +++ ofproto/ofproto-dpif-lsample.h | 5 + ofproto/ofproto-dpif-xlate.c | 251 +++++++++++++++++++++++---------- ofproto/ofproto-dpif-xlate.h | 5 +- ofproto/ofproto-dpif.c | 2 +- tests/ofproto-dpif.at | 146 +++++++++++++++++++ 6 files changed, 345 insertions(+), 80 deletions(-) diff --git a/ofproto/ofproto-dpif-lsample.c b/ofproto/ofproto-dpif-lsample.c index d675a116f..534ad96f0 100644 --- a/ofproto/ofproto-dpif-lsample.c +++ b/ofproto/ofproto-dpif-lsample.c @@ -140,6 +140,22 @@ dpif_lsample_set_options(struct dpif_lsample *lsample, return changed; } +/* Returns the group_id for a given collector_set_id, if it exists. */ +bool +dpif_lsample_get_group_id(struct dpif_lsample *ps, uint32_t collector_set_id, + uint32_t *group_id) +{ + struct lsample_exporter_node *node; + bool found = false; + + node = dpif_lsample_find_exporter_node(ps, collector_set_id); + if (node) { + found = true; + *group_id = node->exporter.options.group_id; + } + return found; +} + struct dpif_lsample * dpif_lsample_create(void) { diff --git a/ofproto/ofproto-dpif-lsample.h b/ofproto/ofproto-dpif-lsample.h index bee36c9c5..9c1026551 100644 --- a/ofproto/ofproto-dpif-lsample.h +++ b/ofproto/ofproto-dpif-lsample.h @@ -18,6 +18,7 @@ #define OFPROTO_DPIF_LSAMPLE_H 1 #include +#include #include struct dpif_lsample; @@ -33,4 +34,8 @@ bool dpif_lsample_set_options(struct dpif_lsample *, const struct ofproto_lsample_options *, size_t n_opts); +bool dpif_lsample_get_group_id(struct dpif_lsample *, + uint32_t collector_set_id, + uint32_t *group_id); + #endif /* OFPROTO_DPIF_LSAMPLE_H */ diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 7c4950895..5e8113d5e 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -47,6 +47,7 @@ #include "ofproto/ofproto-dpif-ipfix.h" #include "ofproto/ofproto-dpif-mirror.h" #include "ofproto/ofproto-dpif-monitor.h" +#include "ofproto/ofproto-dpif-lsample.h" #include "ofproto/ofproto-dpif-sflow.h" #include "ofproto/ofproto-dpif-trace.h" #include "ofproto/ofproto-dpif-xlate-cache.h" @@ -117,6 +118,7 @@ struct xbridge { struct dpif_sflow *sflow; /* SFlow handle, or null. */ struct dpif_ipfix *ipfix; /* Ipfix handle, or null. */ struct netflow *netflow; /* Netflow handle, or null. */ + struct dpif_lsample *lsample; /* Local sample handle, or null. */ struct stp *stp; /* STP or null if disabled. */ struct rstp *rstp; /* RSTP or null if disabled. */ @@ -686,6 +688,7 @@ static void xlate_xbridge_set(struct xbridge *, struct dpif *, const struct mbridge *, const struct dpif_sflow *, const struct dpif_ipfix *, + const struct dpif_lsample *, const struct netflow *, bool forward_bpdu, bool has_in_band, const struct dpif_backer_support *, @@ -1069,6 +1072,7 @@ xlate_xbridge_set(struct xbridge *xbridge, const struct mbridge *mbridge, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, + const struct dpif_lsample *lsample, const struct netflow *netflow, bool forward_bpdu, bool has_in_band, const struct dpif_backer_support *support, @@ -1099,6 +1103,11 @@ xlate_xbridge_set(struct xbridge *xbridge, xbridge->ipfix = dpif_ipfix_ref(ipfix); } + if (xbridge->lsample != lsample) { + dpif_lsample_unref(xbridge->lsample); + xbridge->lsample = dpif_lsample_ref(lsample); + } + if (xbridge->stp != stp) { stp_unref(xbridge->stp); xbridge->stp = stp_ref(stp); @@ -1213,9 +1222,10 @@ xlate_xbridge_copy(struct xbridge *xbridge) xlate_xbridge_set(new_xbridge, xbridge->dpif, xbridge->ml, xbridge->stp, xbridge->rstp, xbridge->ms, xbridge->mbridge, - xbridge->sflow, xbridge->ipfix, xbridge->netflow, - xbridge->forward_bpdu, xbridge->has_in_band, - &xbridge->support, xbridge->addr); + xbridge->sflow, xbridge->ipfix, xbridge->lsample, + xbridge->netflow, xbridge->forward_bpdu, + xbridge->has_in_band, &xbridge->support, + xbridge->addr); LIST_FOR_EACH (xbundle, list_node, &xbridge->xbundles) { xlate_xbundle_copy(new_xbridge, xbundle); } @@ -1372,6 +1382,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, const struct mbridge *mbridge, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, + const struct dpif_lsample *lsample, const struct netflow *netflow, bool forward_bpdu, bool has_in_band, const struct dpif_backer_support *support) @@ -1396,7 +1407,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, old_addr = xbridge->addr; xlate_xbridge_set(xbridge, dpif, ml, stp, rstp, ms, mbridge, sflow, ipfix, - netflow, forward_bpdu, has_in_band, support, + lsample, netflow, forward_bpdu, has_in_band, support, xbridge_addr); if (xbridge_addr != old_addr) { @@ -1428,6 +1439,7 @@ xlate_xbridge_remove(struct xlate_cfg *xcfg, struct xbridge *xbridge) mbridge_unref(xbridge->mbridge); dpif_sflow_unref(xbridge->sflow); dpif_ipfix_unref(xbridge->ipfix); + dpif_lsample_unref(xbridge->lsample); netflow_unref(xbridge->netflow); stp_unref(xbridge->stp); rstp_unref(xbridge->rstp); @@ -3357,58 +3369,92 @@ xlate_normal(struct xlate_ctx *ctx) } } -/* Appends a "sample" action for sFlow or IPFIX to 'ctx->odp_actions'. The - * 'probability' is the number of packets out of UINT32_MAX to sample. The - * 'cookie' is passed back in the callback for each sampled packet. - * 'tunnel_out_port', if not ODPP_NONE, is added as the - * OVS_USERSPACE_ATTR_EGRESS_TUN_PORT attribute. If 'include_actions', - * an OVS_USERSPACE_ATTR_ACTIONS attribute is added. If - * 'emit_set_tunnel', sample(sampling_port=1) would translate into - * datapath sample action set(tunnel(...)), sample(...) and it is used - * for sampling egress tunnel information. - */ +/* Psample-related arguments for compose_sample_action. */ +struct sample_psample_args { + uint32_t group_id; /* Group to be used in psample. */ + struct ofpbuf cookie; /* Cookie to be used in psample. */ +}; + +/* Userspace-related arguments for compose_sample_action. */ +struct sample_userspace_args { + struct user_action_cookie cookie; /* Data passed back in the upcall + * for each sampled packet. */ + odp_port_t tunnel_out_port; /* If not ODPP_NONE, it is added in + * OVS_USERSPACE_ATTR_EGRESS_TUN_PORT + * attribute. */ + bool include_actions; /* Whether OVS_USERSPACE_ATTR_ACTIONS + * is to be set. */ + +}; + +/* Arguments for compose_sample_action. */ +struct compose_sample_args { + uint32_t probability; /* Number of packets out of + * UINT32_MAX to sample. */ + struct sample_userspace_args *userspace; /* Optional, + * arguments for userspace. */ + struct sample_psample_args *psample; /* Optional, + * arguments for psample. */ +}; + +/* Composes sample action according to 'args'. */ static size_t compose_sample_action(struct xlate_ctx *ctx, - const uint32_t probability, - const struct user_action_cookie *cookie, - const odp_port_t tunnel_out_port, - bool include_actions) + const struct compose_sample_args *args) { - if (probability == 0) { + if (args->probability == 0) { /* No need to generate sampling or the inner action. */ return 0; } + /* At least one of userspace or psample config must be provided. */ + ovs_assert(args->userspace || args->psample); + /* If the slow path meter is configured by the controller, * insert a meter action before the user space action. */ struct ofproto *ofproto = &ctx->xin->ofproto->up; uint32_t meter_id = ofproto->slowpath_meter_id; + size_t cookie_offset = 0; + + /* The meter action is only used to throttle userspace actions. + * If they are not needed and the sampling rate is 100%, avoid generating + * a sample action. */ + bool is_sample = (args->probability < UINT32_MAX || + (args->userspace && meter_id != UINT32_MAX)); - /* When meter action is not required, avoid generate sample action - * for 100% sampling rate. */ - bool is_sample = probability < UINT32_MAX || meter_id != UINT32_MAX; size_t sample_offset = 0, actions_offset = 0; if (is_sample) { sample_offset = nl_msg_start_nested(ctx->odp_actions, OVS_ACTION_ATTR_SAMPLE); nl_msg_put_u32(ctx->odp_actions, OVS_SAMPLE_ATTR_PROBABILITY, - probability); + args->probability); actions_offset = nl_msg_start_nested(ctx->odp_actions, OVS_SAMPLE_ATTR_ACTIONS); } - if (meter_id != UINT32_MAX) { - nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_METER, meter_id); + if (args->psample) { + odp_put_psample_action(ctx->odp_actions, + args->psample->group_id, + args->psample->cookie.data, + args->psample->cookie.size); + } + + if (args->userspace) { + if (meter_id != UINT32_MAX) { + nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_METER, meter_id); + } + + odp_port_t odp_port = ofp_port_to_odp_port( + ctx->xbridge, ctx->xin->flow.in_port.ofp_port); + uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port); + int res = odp_put_userspace_action(pid, &args->userspace->cookie, + sizeof args->userspace->cookie, + args->userspace->tunnel_out_port, + args->userspace->include_actions, + ctx->odp_actions, &cookie_offset); + ovs_assert(res == 0); } - odp_port_t odp_port = ofp_port_to_odp_port( - ctx->xbridge, ctx->xin->flow.in_port.ofp_port); - uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port); - size_t cookie_offset; - int res = odp_put_userspace_action(pid, cookie, sizeof *cookie, - tunnel_out_port, include_actions, - ctx->odp_actions, &cookie_offset); - ovs_assert(res == 0); if (is_sample) { nl_msg_end_nested(ctx->odp_actions, actions_offset); nl_msg_end_nested(ctx->odp_actions, sample_offset); @@ -3428,19 +3474,23 @@ static size_t compose_sflow_action(struct xlate_ctx *ctx) { struct dpif_sflow *sflow = ctx->xbridge->sflow; + struct sample_userspace_args userspace = {}; + struct compose_sample_args args = {}; + if (!sflow || ctx->xin->flow.in_port.ofp_port == OFPP_NONE) { return 0; } - struct user_action_cookie cookie; + userspace.cookie.type = USER_ACTION_COOKIE_SFLOW; + userspace.cookie.ofp_in_port = ctx->xin->flow.in_port.ofp_port; + userspace.cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid; + userspace.tunnel_out_port = ODPP_NONE; + userspace.include_actions = true; - memset(&cookie, 0, sizeof cookie); - cookie.type = USER_ACTION_COOKIE_SFLOW; - cookie.ofp_in_port = ctx->xin->flow.in_port.ofp_port; - cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid; + args.probability = dpif_sflow_get_probability(sflow); + args.userspace = &userspace; - return compose_sample_action(ctx, dpif_sflow_get_probability(sflow), - &cookie, ODPP_NONE, true); + return compose_sample_action(ctx, &args); } /* If flow IPFIX is enabled, make sure IPFIX flow sample action @@ -3451,7 +3501,10 @@ static void compose_ipfix_action(struct xlate_ctx *ctx, odp_port_t output_odp_port) { struct dpif_ipfix *ipfix = ctx->xbridge->ipfix; - odp_port_t tunnel_out_port = ODPP_NONE; + struct sample_userspace_args userspace = {0}; + struct compose_sample_args args = {0}; + + userspace.tunnel_out_port = ODPP_NONE; if (!ipfix || (output_odp_port == ODPP_NONE && @@ -3476,21 +3529,20 @@ compose_ipfix_action(struct xlate_ctx *ctx, odp_port_t output_odp_port) */ if (dpif_ipfix_get_bridge_exporter_tunnel_sampling(ipfix) && dpif_ipfix_is_tunnel_port(ipfix, output_odp_port) ) { - tunnel_out_port = output_odp_port; + userspace.tunnel_out_port = output_odp_port; } } - struct user_action_cookie cookie; + userspace.cookie.type = USER_ACTION_COOKIE_IPFIX; + userspace.cookie.ofp_in_port = ctx->xin->flow.in_port.ofp_port; + userspace.cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid; + userspace.cookie.ipfix.output_odp_port = output_odp_port; + userspace.include_actions = false; - memset(&cookie, 0, sizeof cookie); - cookie.type = USER_ACTION_COOKIE_IPFIX; - cookie.ofp_in_port = ctx->xin->flow.in_port.ofp_port; - cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid; - cookie.ipfix.output_odp_port = output_odp_port; + args.probability = dpif_ipfix_get_bridge_exporter_probability(ipfix); + args.userspace = &userspace; - compose_sample_action(ctx, - dpif_ipfix_get_bridge_exporter_probability(ipfix), - &cookie, tunnel_out_port, false); + compose_sample_action(ctx, &args); } /* Fix "sample" action according to data collected while composing ODP actions, @@ -5847,22 +5899,16 @@ xlate_fin_timeout(struct xlate_ctx *ctx, } static void -xlate_sample_action(struct xlate_ctx *ctx, - const struct ofpact_sample *os) +xlate_fill_ipfix_sample(struct xlate_ctx *ctx, + const struct ofpact_sample *os, + const struct dpif_ipfix *ipfix, + struct sample_userspace_args *userspace) { odp_port_t output_odp_port = ODPP_NONE; - odp_port_t tunnel_out_port = ODPP_NONE; - struct dpif_ipfix *ipfix = ctx->xbridge->ipfix; bool emit_set_tunnel = false; - if (!ipfix) { - return; - } - - /* Scale the probability from 16-bit to 32-bit while representing - * the same percentage. */ - uint32_t probability = - ((uint32_t) os->probability << 16) | os->probability; + memset(userspace, 0, sizeof *userspace); + userspace->tunnel_out_port = ODPP_NONE; /* If ofp_port in flow sample action is equel to ofp_port, * this sample action is a input port action. */ @@ -5879,7 +5925,7 @@ xlate_sample_action(struct xlate_ctx *ctx, if (dpif_ipfix_get_flow_exporter_tunnel_sampling(ipfix, os->collector_set_id) && dpif_ipfix_is_tunnel_port(ipfix, output_odp_port)) { - tunnel_out_port = output_odp_port; + userspace->tunnel_out_port = output_odp_port; emit_set_tunnel = true; } } @@ -5913,20 +5959,71 @@ xlate_sample_action(struct xlate_ctx *ctx, } } - struct user_action_cookie cookie; + userspace->cookie.type = USER_ACTION_COOKIE_FLOW_SAMPLE; + userspace->cookie.ofp_in_port = ctx->xin->flow.in_port.ofp_port; + userspace->cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid; + userspace->cookie.flow_sample.probability = os->probability; + userspace->cookie.flow_sample.collector_set_id = os->collector_set_id; + userspace->cookie.flow_sample.obs_domain_id = os->obs_domain_id; + userspace->cookie.flow_sample.obs_point_id = os->obs_point_id; + userspace->cookie.flow_sample.output_odp_port = output_odp_port; + userspace->cookie.flow_sample.direction = os->direction; + userspace->include_actions = false; +} - memset(&cookie, 0, sizeof cookie); - cookie.type = USER_ACTION_COOKIE_FLOW_SAMPLE; - cookie.ofp_in_port = ctx->xin->flow.in_port.ofp_port; - cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid; - cookie.flow_sample.probability = os->probability; - cookie.flow_sample.collector_set_id = os->collector_set_id; - cookie.flow_sample.obs_domain_id = os->obs_domain_id; - cookie.flow_sample.obs_point_id = os->obs_point_id; - cookie.flow_sample.output_odp_port = output_odp_port; - cookie.flow_sample.direction = os->direction; - - compose_sample_action(ctx, probability, &cookie, tunnel_out_port, false); +static void +xlate_sample_action(struct xlate_ctx *ctx, + const struct ofpact_sample *os) +{ + uint8_t cookie_buf[sizeof(os->obs_domain_id) + sizeof(os->obs_point_id)]; + struct dpif_lsample *lsample = ctx->xbridge->lsample; + struct dpif_ipfix *ipfix = ctx->xbridge->ipfix; + struct compose_sample_args compose_args = {}; + struct sample_userspace_args userspace; + struct sample_psample_args psample; + + if (!ipfix && !lsample) { + return; + } + + /* Scale the probability from 16-bit to 32-bit while representing + * the same percentage. */ + compose_args.probability = + ((uint32_t) os->probability << 16) | os->probability; + + if (ipfix) { + xlate_fill_ipfix_sample(ctx, os, ipfix, &userspace); + compose_args.userspace = &userspace; + } + + if (lsample && + dpif_lsample_get_group_id(lsample, + os->collector_set_id, + &psample.group_id)) { + ovs_be32 *data; + + ofpbuf_use_stub(&psample.cookie, cookie_buf, sizeof cookie_buf); + + data = ofpbuf_put_uninit(&psample.cookie, + sizeof(os->obs_domain_id)); + *data = htonl(os->obs_domain_id); + + data = ofpbuf_put_uninit(&psample.cookie, + sizeof(os->obs_point_id)); + *data = htonl(os->obs_point_id); + + compose_args.psample = &psample; + } + + if (!compose_args.userspace && !compose_args.psample) { + return; + } + + compose_sample_action(ctx, &compose_args); + + if (compose_args.psample) { + ofpbuf_uninit(&compose_args.psample->cookie); + } } /* Determine if an datapath action translated from the openflow action diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index 05b46fb26..08f9397d8 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -176,8 +176,9 @@ void xlate_ofproto_set(struct ofproto_dpif *, const char *name, struct dpif *, const struct mac_learning *, struct stp *, struct rstp *, const struct mcast_snooping *, const struct mbridge *, const struct dpif_sflow *, - const struct dpif_ipfix *, const struct netflow *, - bool forward_bpdu, bool has_in_band, + const struct dpif_ipfix *, const struct dpif_lsample *, + const struct netflow *, bool forward_bpdu, + bool has_in_band, const struct dpif_backer_support *support); void xlate_remove_ofproto(struct ofproto_dpif *); struct ofproto_dpif *xlate_ofproto_lookup(const struct uuid *uuid); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 56830c630..006f67b01 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -485,7 +485,7 @@ type_run(const char *type) ofproto->backer->dpif, ofproto->ml, ofproto->stp, ofproto->rstp, ofproto->ms, ofproto->mbridge, ofproto->sflow, ofproto->ipfix, - ofproto->netflow, + ofproto->lsample, ofproto->netflow, ofproto->up.forward_bpdu, connmgr_has_in_band(ofproto->up.connmgr), &ofproto->backer->rt_support); diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index 0b23fd6c5..2a04977a7 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -12136,3 +12136,149 @@ AT_CHECK([test 1 = `ovs-ofctl parse-pcap p2-tx.pcap | wc -l`]) OVS_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([ofproto-dpif - Local sampling - not supported]) +OVS_VSWITCHD_START +add_of_ports br0 1 2 + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \ + -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12], + [0], [ignore]) + +AT_DATA([flows.txt], [dnl +in_port=1 actions=sample(probability=32767,obs_domain_id=100,obs_point_id=200),2 +]) + +AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt]) + +m4_define([TRACE_PKT], [m4_join([,], + [in_port(1)], + [eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)], + [ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no)], + [icmp(type=8,code=0)])]) + +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'TRACE_PKT'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: 2 +]) + +OVS_VSWITCHD_STOP(["/ignoring local sampling configuration: not supported by this datapath/d"]) +AT_CLEANUP + +AT_SETUP([ofproto-dpif - Local sampling - sanity check]) +OVS_VSWITCHD_START +add_of_ports br0 1 2 3 + +AT_CHECK([ovs-appctl dpif/set-dp-features --force br0 psample true], [0], [ignore]) + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=42], + [0], [ignore]) + +AT_DATA([flows.txt], [dnl +in_port=1, actions=sample(probability=32767,collector_set_id=1,obs_domain_id=100,obs_point_id=200),3 +in_port=2, actions=sample(probability=32767,collector_set_id=20,obs_domain_id=100,obs_point_id=200),3 +]) + +AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt]) + +m4_define([TRACE_PKT], [m4_join([,], + [eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)], + [ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no)], + [icmp(type=8,code=0)])]) + +dnl collector_set_id does not match. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2) TRACE_PKT'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: 3 +]) + +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1) TRACE_PKT'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: sample(sample=50.0%,actions(psample(group=42,cookie=0x64000000c8))),3 +]) + +OVS_VSWITCHD_STOP() +AT_CLEANUP + +AT_SETUP([ofproto-dpif - Local sampling - with IPFIX]) +OVS_VSWITCHD_START +add_of_ports br0 1 2 + +AT_CHECK([ovs-appctl dpif/set-dp-features --force br0 psample true], [0], [ignore]) + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- --id=@i create ipfix targets=\"127.0.0.1:4739\" \ + -- create Flow_Sample_Collector_Set ipfix=@i id=1 bridge=@br0 local_group_id=42], + [0], [ignore]) + +AT_DATA([flows.txt], [dnl +in_port=1, actions=sample(probability=32767,collector_set_id=1,obs_domain_id=100,obs_point_id=200),2 +]) + +AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt]) + +m4_define([TRACE_PKT], [m4_join([,], + [eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)], + [ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no)], + [icmp(type=8,code=0)])]) + +m4_define([EXPECTED_ACT], [m4_join([], + [sample(sample=50.0%,actions(], + [psample(group=42,cookie=0x64000000c8),], + [userspace(pid=0,], + [flow_sample(probability=32767,collector_set_id=1,obs_domain_id=100,obs_point_id=200,output_port=4294967295)], + [))),], + [2], +)]) + +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1) TRACE_PKT'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: EXPECTED_ACT +]) + +OVS_VSWITCHD_STOP() +AT_CLEANUP + +AT_SETUP([ofproto-dpif - Local sampling - with metered IPFIX]) +OVS_VSWITCHD_START +add_of_ports br0 1 2 + +AT_CHECK([ovs-appctl dpif/set-dp-features --force br0 psample true], [0], [ignore]) + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- --id=@i create ipfix targets=\"127.0.0.1:4739\" \ + -- create Flow_Sample_Collector_Set ipfix=@i id=1 bridge=@br0 local_group_id=42], + [0], [ignore]) + +AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=slowpath pktps stats bands=type=drop rate=2']) + +AT_DATA([flows.txt], [dnl +in_port=1, actions=sample(probability=32767,collector_set_id=1,obs_domain_id=100,obs_point_id=200),2 +]) + +AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt]) + +m4_define([TRACE_PKT], [m4_join([,], + [eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)], + [ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no)], + [icmp(type=8,code=0)])]) + +m4_define([EXPECTED_ACT], [m4_join([], + [sample(sample=50.0%,actions(], + [psample(group=42,cookie=0x64000000c8),], + [meter(0),], + [userspace(pid=0,], + [flow_sample(probability=32767,collector_set_id=1,obs_domain_id=100,obs_point_id=200,output_port=4294967295)], + [))),], + [2], +)]) + +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1) TRACE_PKT'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: EXPECTED_ACT +]) + +OVS_VSWITCHD_STOP() +AT_CLEANUP From patchwork Thu Jul 4 07:52:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956707 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=P1yOz8N9; 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 4WF85w3gc7z1xpP for ; Thu, 4 Jul 2024 17:53:24 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 0CF6D410DE; Thu, 4 Jul 2024 07:53:22 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id V1ooBvEx9DwV; Thu, 4 Jul 2024 07:53:18 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 0B5994109F Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=P1yOz8N9 Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id 0B5994109F; Thu, 4 Jul 2024 07:53:17 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 08453C0A9D; Thu, 4 Jul 2024 07:53:17 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 36289C0A9F for ; Thu, 4 Jul 2024 07:53:15 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 3B08660796 for ; Thu, 4 Jul 2024 07:53:14 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 8watBtDd6vLp for ; Thu, 4 Jul 2024 07:53:12 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp3.osuosl.org 8AAEF60B42 Authentication-Results: smtp3.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 8AAEF60B42 Authentication-Results: smtp3.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=P1yOz8N9 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id 8AAEF60B42 for ; Thu, 4 Jul 2024 07:53:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079591; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5yE82BMVBffHCvYwtkhweeQjkMk8H+leq8mJpBiJ5/c=; b=P1yOz8N95+0x4Ct/SEm/y0RokTPzJ9knkM8PuI0g0OR1aPyarYrKflao8W5wdT8nnNxpRp 3gjeB2dCljiUlk8OmLi3ULm/aCwu7S1+3J4xAPml902KSOTgzoCdWczQ6BHyCPUsO2RO6r wBzFP6wg9T6w8H0TUYSClmnZAMPMeDk= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-633-SOgSmul5MXWcCyxwlMv_6w-1; Thu, 04 Jul 2024 03:53:09 -0400 X-MC-Unique: SOgSmul5MXWcCyxwlMv_6w-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D663B19560AD for ; Thu, 4 Jul 2024 07:53:08 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CE5D71956046; Thu, 4 Jul 2024 07:53:07 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:48 +0200 Message-ID: <20240704075255.140530-8-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 07/13] ofproto-dpif-xlate-cache: Add lsample to xcache. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Add a cache entry type for local sample objects. Store both the dpif_lsample reference and the collector_set_id so we can quickly find the particular exporter. Using this mechanism, account for packet and byte statistics. Signed-off-by: Adrian Moreno --- ofproto/ofproto-dpif-lsample.c | 18 ++++++++++++++++++ ofproto/ofproto-dpif-lsample.h | 4 ++++ ofproto/ofproto-dpif-xlate-cache.c | 11 ++++++++++- ofproto/ofproto-dpif-xlate-cache.h | 6 ++++++ ofproto/ofproto-dpif-xlate.c | 14 ++++++++++++++ ofproto/ofproto-dpif.c | 1 + 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/ofproto/ofproto-dpif-lsample.c b/ofproto/ofproto-dpif-lsample.c index 534ad96f0..171129d5b 100644 --- a/ofproto/ofproto-dpif-lsample.c +++ b/ofproto/ofproto-dpif-lsample.c @@ -18,6 +18,7 @@ #include "ofproto-dpif-lsample.h" #include "cmap.h" +#include "dpif.h" #include "hash.h" #include "ofproto.h" #include "openvswitch/thread.h" @@ -44,6 +45,8 @@ struct dpif_lsample { struct lsample_exporter { struct ofproto_lsample_options options; + atomic_uint64_t n_packets; + atomic_uint64_t n_bytes; }; struct lsample_exporter_node { @@ -156,6 +159,21 @@ dpif_lsample_get_group_id(struct dpif_lsample *ps, uint32_t collector_set_id, return found; } +void +dpif_lsample_credit_stats(struct dpif_lsample *lsample, + uint32_t collector_set_id, + const struct dpif_flow_stats *stats) +{ + struct lsample_exporter_node *node; + uint64_t orig; + + node = dpif_lsample_find_exporter_node(lsample, collector_set_id); + if (node) { + atomic_add_relaxed(&node->exporter.n_packets, stats->n_packets, &orig); + atomic_add_relaxed(&node->exporter.n_bytes, stats->n_bytes, &orig); + } +} + struct dpif_lsample * dpif_lsample_create(void) { diff --git a/ofproto/ofproto-dpif-lsample.h b/ofproto/ofproto-dpif-lsample.h index 9c1026551..2666e5478 100644 --- a/ofproto/ofproto-dpif-lsample.h +++ b/ofproto/ofproto-dpif-lsample.h @@ -23,6 +23,7 @@ struct dpif_lsample; struct ofproto_lsample_options; +struct dpif_flow_stats; struct dpif_lsample *dpif_lsample_create(void); @@ -38,4 +39,7 @@ bool dpif_lsample_get_group_id(struct dpif_lsample *, uint32_t collector_set_id, uint32_t *group_id); +void dpif_lsample_credit_stats(struct dpif_lsample *, + uint32_t collector_set_id, + const struct dpif_flow_stats *); #endif /* OFPROTO_DPIF_LSAMPLE_H */ diff --git a/ofproto/ofproto-dpif-xlate-cache.c b/ofproto/ofproto-dpif-xlate-cache.c index 2e1fcb3a6..73d79bfc7 100644 --- a/ofproto/ofproto-dpif-xlate-cache.c +++ b/ofproto/ofproto-dpif-xlate-cache.c @@ -35,9 +35,10 @@ #include "learn.h" #include "mac-learning.h" #include "netdev-vport.h" +#include "ofproto/ofproto-dpif.h" +#include "ofproto/ofproto-dpif-lsample.h" #include "ofproto/ofproto-dpif-mirror.h" #include "ofproto/ofproto-dpif-xlate.h" -#include "ofproto/ofproto-dpif.h" #include "ofproto/ofproto-provider.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/vlog.h" @@ -162,6 +163,11 @@ xlate_push_stats_entry(struct xc_entry *entry, } break; + case XC_LSAMPLE: + dpif_lsample_credit_stats(entry->lsample.lsample, + entry->lsample.collector_set_id, + stats); + break; default: OVS_NOT_REACHED(); } @@ -245,6 +251,9 @@ xlate_cache_clear_entry(struct xc_entry *entry) break; case XC_TUNNEL_HEADER: break; + case XC_LSAMPLE: + dpif_lsample_unref(entry->lsample.lsample); + break; default: OVS_NOT_REACHED(); } diff --git a/ofproto/ofproto-dpif-xlate-cache.h b/ofproto/ofproto-dpif-xlate-cache.h index 0fc6d2ea6..df8115419 100644 --- a/ofproto/ofproto-dpif-xlate-cache.h +++ b/ofproto/ofproto-dpif-xlate-cache.h @@ -29,6 +29,7 @@ struct bfd; struct bond; struct dpif_flow_stats; +struct dpif_lsample; struct flow; struct group_dpif; struct mbridge; @@ -53,6 +54,7 @@ enum xc_type { XC_GROUP, XC_TNL_NEIGH, XC_TUNNEL_HEADER, + XC_LSAMPLE, }; /* xlate_cache entries hold enough information to perform the side effects of @@ -126,6 +128,10 @@ struct xc_entry { } operation; uint16_t hdr_size; } tunnel_hdr; + struct { + struct dpif_lsample *lsample; + uint32_t collector_set_id; + } lsample; }; }; diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 5e8113d5e..b9546dc5b 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2361,6 +2361,7 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle, ctx->xin->resubmit_stats->n_packets, ctx->xin->resubmit_stats->n_bytes); } + if (ctx->xin->xcache) { struct xc_entry *entry; @@ -6013,6 +6014,19 @@ xlate_sample_action(struct xlate_ctx *ctx, *data = htonl(os->obs_point_id); compose_args.psample = &psample; + + if (ctx->xin->resubmit_stats) { + dpif_lsample_credit_stats(lsample, + os->collector_set_id, + ctx->xin->resubmit_stats); + } + if (ctx->xin->xcache) { + struct xc_entry *entry; + + entry = xlate_cache_add_entry(ctx->xin->xcache, XC_LSAMPLE); + entry->lsample.lsample = dpif_lsample_ref(lsample); + entry->lsample.collector_set_id = os->collector_set_id; + } } if (!compose_args.userspace && !compose_args.psample) { diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 006f67b01..28c564846 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -5156,6 +5156,7 @@ ofproto_dpif_xcache_execute(struct ofproto_dpif *ofproto, case XC_GROUP: case XC_TNL_NEIGH: case XC_TUNNEL_HEADER: + case XC_LSAMPLE: xlate_push_stats_entry(entry, stats, false); break; default: From patchwork Thu Jul 4 07:52:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956708 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=aoJltTZQ; 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 4WF8621tLzz1xpP for ; Thu, 4 Jul 2024 17:53:30 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 82EDA413B5; Thu, 4 Jul 2024 07:53:28 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id MTSQ6uPekzbe; Thu, 4 Jul 2024 07:53:26 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 8ABA2409FE Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=aoJltTZQ Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id 8ABA2409FE; Thu, 4 Jul 2024 07:53:25 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1C796C0A9E; Thu, 4 Jul 2024 07:53:25 +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 202C9C0A9B for ; Thu, 4 Jul 2024 07:53:24 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 722F7847CB for ; Thu, 4 Jul 2024 07:53:17 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id ZH1BjJaIniXG for ; Thu, 4 Jul 2024 07:53:15 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org 5714E847C4 Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 5714E847C4 Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=aoJltTZQ Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id 5714E847C4 for ; Thu, 4 Jul 2024 07:53:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079593; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cuKY1rxRUX2beyzVJH/OVI1klSewwzbA9sPnF3MHuAA=; b=aoJltTZQ7C0whyZV2pkLxXK7+q0191T3I6GvVhEUKqef6urR+eXhAQmy8KgdhLXIUK5ZTF RNAXbLAz5r7rGxJJm6KMboGdc9Cwca0hFK7Z/Ib30nKiYuQFIwjzrqIeH4m+gSYOzU6Dlt /0U1IEDvPZeP7pnU6PXVrLfKOgK0i3k= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-639-h55Lp_OXPNGAzz5oWQHp-w-1; Thu, 04 Jul 2024 03:53:11 -0400 X-MC-Unique: h55Lp_OXPNGAzz5oWQHp-w-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 78C7E19560A3 for ; Thu, 4 Jul 2024 07:53:10 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 546321956046; Thu, 4 Jul 2024 07:53:09 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:49 +0200 Message-ID: <20240704075255.140530-9-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 08/13] ofproto-dpif-lsample: Show stats via unixctl. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Add a command to dump statistics per exporter. Signed-off-by: Adrian Moreno --- NEWS | 2 + ofproto/ofproto-dpif-lsample.c | 111 +++++++++++++++++++++++++++++++++ ofproto/ofproto-dpif-lsample.h | 1 + ofproto/ofproto-dpif.c | 1 + 4 files changed, 115 insertions(+) diff --git a/NEWS b/NEWS index 15faf9fc3..1c53badea 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,8 @@ Post-v3.3.0 allows samples to be emitted locally (instead of via IPFIX) in a datapath-specific manner. The Linux kernel datapath is the first to support this feature by using the new datapath "psample" action. + A new unixctl command 'lsample/show' shows packet and bytes statistics + per local sample exporter. v3.3.0 - 16 Feb 2024 diff --git a/ofproto/ofproto-dpif-lsample.c b/ofproto/ofproto-dpif-lsample.c index 171129d5b..82a87c27d 100644 --- a/ofproto/ofproto-dpif-lsample.c +++ b/ofproto/ofproto-dpif-lsample.c @@ -21,7 +21,10 @@ #include "dpif.h" #include "hash.h" #include "ofproto.h" +#include "ofproto-dpif.h" +#include "openvswitch/dynamic-string.h" #include "openvswitch/thread.h" +#include "unixctl.h" /* Dpif local sampling. * @@ -219,3 +222,111 @@ dpif_lsample_unref(struct dpif_lsample *lsample) dpif_lsample_destroy(lsample); } } + +static int +comp_exporter_collector_id(const void *a_, const void *b_) +{ + const struct lsample_exporter_node *a, *b; + + a = *(struct lsample_exporter_node **) a_; + b = *(struct lsample_exporter_node **) b_; + + if (a->exporter.options.collector_set_id > + b->exporter.options.collector_set_id) { + return 1; + } + if (a->exporter.options.collector_set_id < + b->exporter.options.collector_set_id) { + return -1; + } + return 0; +} + +static void +lsample_exporter_list(struct dpif_lsample *lsample, + struct lsample_exporter_node ***list, + size_t *num_exporters) +{ + struct lsample_exporter_node **exporter_list; + struct lsample_exporter_node *node; + size_t k = 0, n; + + n = cmap_count(&lsample->exporters); + + exporter_list = xcalloc(n, sizeof *exporter_list); + + CMAP_FOR_EACH (node, node, &lsample->exporters) { + if (k >= n) { + break; + } + exporter_list[k++] = node; + } + + qsort(exporter_list, k, sizeof *exporter_list, comp_exporter_collector_id); + + *list = exporter_list; + *num_exporters = k; +} + +static void +lsample_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) +{ + struct lsample_exporter_node **node_list = NULL; + struct ds ds = DS_EMPTY_INITIALIZER; + const struct ofproto_dpif *ofproto; + size_t i, num; + + ofproto = ofproto_dpif_lookup_by_name(argv[1]); + if (!ofproto) { + unixctl_command_reply_error(conn, "no such bridge"); + return; + } + + if (!ofproto->lsample) { + unixctl_command_reply_error(conn, + "no local sampling exporters configured"); + return; + } + + ds_put_format(&ds, "Local sample statistics for bridge \"%s\":\n", + argv[1]); + + lsample_exporter_list(ofproto->lsample, &node_list, &num); + + for (i = 0; i < num; i++) { + uint64_t n_bytes; + uint64_t n_packets; + + struct lsample_exporter_node *node = node_list[i]; + + atomic_read_relaxed(&node->exporter.n_packets, &n_packets); + atomic_read_relaxed(&node->exporter.n_bytes, &n_bytes); + + if (i) { + ds_put_cstr(&ds, "\n"); + } + + ds_put_format(&ds, "Collector Set ID: %"PRIu32":\n", + node->exporter.options.collector_set_id); + ds_put_format(&ds, " Group ID : %"PRIu32"\n", + node->exporter.options.group_id); + ds_put_format(&ds, " Total packets: %"PRIu64"\n", n_packets); + ds_put_format(&ds, " Total bytes : %"PRIu64"\n", n_bytes); + } + + free(node_list); + unixctl_command_reply(conn, ds_cstr(&ds)); + ds_destroy(&ds); +} + +void dpif_lsample_init(void) +{ + static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; + + if (ovsthread_once_start(&once)) { + unixctl_command_register("lsample/show", "bridge", 1, 1, + lsample_unixctl_show, NULL); + ovsthread_once_done(&once); + } +} diff --git a/ofproto/ofproto-dpif-lsample.h b/ofproto/ofproto-dpif-lsample.h index 2666e5478..692ac26e6 100644 --- a/ofproto/ofproto-dpif-lsample.h +++ b/ofproto/ofproto-dpif-lsample.h @@ -38,6 +38,7 @@ bool dpif_lsample_set_options(struct dpif_lsample *, bool dpif_lsample_get_group_id(struct dpif_lsample *, uint32_t collector_set_id, uint32_t *group_id); +void dpif_lsample_init(void); void dpif_lsample_credit_stats(struct dpif_lsample *, uint32_t collector_set_id, diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 28c564846..ee8fbaa9a 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -286,6 +286,7 @@ init(const struct shash *iface_hints) ofproto_unixctl_init(); ofproto_dpif_trace_init(); udpif_init(); + dpif_lsample_init(); } static void From patchwork Thu Jul 4 07:52:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956712 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=WUTTqgxd; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (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 4WF86Z03hlz1xpP for ; Thu, 4 Jul 2024 17:53:58 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 4A9976126F; Thu, 4 Jul 2024 07:53:56 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 5ghznCdTyxKJ; Thu, 4 Jul 2024 07:53:53 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org A0D4C60B66 Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=WUTTqgxd Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id A0D4C60B66; Thu, 4 Jul 2024 07:53:43 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 48635C0A97; Thu, 4 Jul 2024 07:53:43 +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 14A77C0A97 for ; Thu, 4 Jul 2024 07:53:42 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id ED9DA84829 for ; Thu, 4 Jul 2024 07:53:25 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id T7uyQcTqqPjp for ; Thu, 4 Jul 2024 07:53:16 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org 70803847CD Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 70803847CD Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=WUTTqgxd Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id 70803847CD for ; Thu, 4 Jul 2024 07:53:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079594; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=A4/CUl6xR0nSufYKQG9/3Xx1TQjvaSlDfEhDUWxxskw=; b=WUTTqgxdJMjIG7LNemlJ+9Nz/G5xONfpnvPrJpErDPf0Zs4jjB2I4Li1zxGzQ1x52JlFa0 cU8R6HbqVQcJiPcLlyYdl/7nrhA7riZU0HRCP1g26tFZvsQelmy0aClL7uhy8JHeDFF7r4 yKwP/o4BxK6TmD0Ok0RrCfdcG8I/6oY= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-557-I0zowtR9M0eXubLaEdJmLw-1; Thu, 04 Jul 2024 03:53:12 -0400 X-MC-Unique: I0zowtR9M0eXubLaEdJmLw-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1331F1955F45 for ; Thu, 4 Jul 2024 07:53:12 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C52921955F65; Thu, 4 Jul 2024 07:53:10 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:50 +0200 Message-ID: <20240704075255.140530-10-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 09/13] tests: Add test-psample testing utility. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This simple program reads from psample and prints the packets to stdout. Signed-off-by: Adrian Moreno --- include/linux/automake.mk | 1 + include/linux/psample.h | 68 +++++++++ tests/automake.mk | 3 +- tests/test-psample.c | 284 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 355 insertions(+), 1 deletion(-) create mode 100644 include/linux/psample.h create mode 100644 tests/test-psample.c diff --git a/include/linux/automake.mk b/include/linux/automake.mk index cdae5eedc..ac306b53c 100644 --- a/include/linux/automake.mk +++ b/include/linux/automake.mk @@ -3,6 +3,7 @@ noinst_HEADERS += \ include/linux/netfilter/nf_conntrack_sctp.h \ include/linux/openvswitch.h \ include/linux/pkt_cls.h \ + include/linux/psample.h \ include/linux/gen_stats.h \ include/linux/tc_act/tc_mpls.h \ include/linux/tc_act/tc_pedit.h \ diff --git a/include/linux/psample.h b/include/linux/psample.h new file mode 100644 index 000000000..d5761b730 --- /dev/null +++ b/include/linux/psample.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_PSAMPLE_H +#define __LINUX_PSAMPLE_H + +enum { + PSAMPLE_ATTR_IIFINDEX, + PSAMPLE_ATTR_OIFINDEX, + PSAMPLE_ATTR_ORIGSIZE, + PSAMPLE_ATTR_SAMPLE_GROUP, + PSAMPLE_ATTR_GROUP_SEQ, + PSAMPLE_ATTR_SAMPLE_RATE, + PSAMPLE_ATTR_DATA, + PSAMPLE_ATTR_GROUP_REFCOUNT, + PSAMPLE_ATTR_TUNNEL, + + PSAMPLE_ATTR_PAD, + PSAMPLE_ATTR_OUT_TC, /* u16 */ + PSAMPLE_ATTR_OUT_TC_OCC, /* u64, bytes */ + PSAMPLE_ATTR_LATENCY, /* u64, nanoseconds */ + PSAMPLE_ATTR_TIMESTAMP, /* u64, nanoseconds */ + PSAMPLE_ATTR_PROTO, /* u16 */ + PSAMPLE_ATTR_USER_COOKIE, /* binary, user provided data */ + PSAMPLE_ATTR_SAMPLE_PROBABILITY,/* no argument, interpret rate in + * PSAMPLE_ATTR_SAMPLE_RATE as a + * probability scaled 0 - U32_MAX. + */ + + __PSAMPLE_ATTR_MAX +}; + +enum psample_command { + PSAMPLE_CMD_SAMPLE, + PSAMPLE_CMD_GET_GROUP, + PSAMPLE_CMD_NEW_GROUP, + PSAMPLE_CMD_DEL_GROUP, + PSAMPLE_CMD_SAMPLE_FILTER_SET, +}; + +enum psample_tunnel_key_attr { + PSAMPLE_TUNNEL_KEY_ATTR_ID, /* be64 Tunnel ID */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV4_SRC, /* be32 src IP address. */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV4_DST, /* be32 dst IP address. */ + PSAMPLE_TUNNEL_KEY_ATTR_TOS, /* u8 Tunnel IP ToS. */ + PSAMPLE_TUNNEL_KEY_ATTR_TTL, /* u8 Tunnel IP TTL. */ + PSAMPLE_TUNNEL_KEY_ATTR_DONT_FRAGMENT, /* No argument, set DF. */ + PSAMPLE_TUNNEL_KEY_ATTR_CSUM, /* No argument. CSUM packet. */ + PSAMPLE_TUNNEL_KEY_ATTR_OAM, /* No argument. OAM frame. */ + PSAMPLE_TUNNEL_KEY_ATTR_GENEVE_OPTS, /* Array of Geneve options. */ + PSAMPLE_TUNNEL_KEY_ATTR_TP_SRC, /* be16 src Transport Port. */ + PSAMPLE_TUNNEL_KEY_ATTR_TP_DST, /* be16 dst Transport Port. */ + PSAMPLE_TUNNEL_KEY_ATTR_VXLAN_OPTS, /* Nested VXLAN opts* */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV6_SRC, /* struct in6_addr src IPv6 address. */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */ + PSAMPLE_TUNNEL_KEY_ATTR_PAD, + PSAMPLE_TUNNEL_KEY_ATTR_ERSPAN_OPTS, /* struct erspan_metadata */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE, /* No argument. IPV4_INFO_BRIDGE mode.*/ + __PSAMPLE_TUNNEL_KEY_ATTR_MAX +}; + +/* Can be overridden at runtime by module option */ +#define PSAMPLE_ATTR_MAX (__PSAMPLE_ATTR_MAX - 1) + +#define PSAMPLE_NL_MCGRP_CONFIG_NAME "config" +#define PSAMPLE_NL_MCGRP_SAMPLE_NAME "packets" +#define PSAMPLE_GENL_NAME "psample" +#define PSAMPLE_GENL_VERSION 1 + +#endif diff --git a/tests/automake.mk b/tests/automake.mk index 04f48f2d8..edfc2cb33 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -499,7 +499,8 @@ endif if LINUX tests_ovstest_SOURCES += \ tests/test-netlink-conntrack.c \ - tests/test-netlink-policy.c + tests/test-netlink-policy.c \ + tests/test-psample.c endif tests_ovstest_LDADD = lib/libopenvswitch.la diff --git a/tests/test-psample.c b/tests/test-psample.c new file mode 100644 index 000000000..6c4606ef5 --- /dev/null +++ b/tests/test-psample.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#undef NDEBUG +#include +#include +#include +#include +#include + +#include + +#include "command-line.h" +#include "dp-packet.h" +#include "util.h" +#include "netlink.h" +#include "netlink-socket.h" +#include "openvswitch/ofp-actions.h" +#include "openvswitch/ofp-print.h" +#include "openvswitch/types.h" +#include "openvswitch/uuid.h" +#include "openvswitch/vlog.h" +#include "ovstest.h" + +VLOG_DEFINE_THIS_MODULE(test_psample); + +static int psample_family = 0; +static uint32_t group_id = 0; +static bool has_filter; + +static void usage(void) +{ + printf("%s: psample collector test utility\n" + "usage: %s [OPTIONS] [GROUP]\n" + "where GROUP is the psample group_id to listen on. " + "If none is provided all events are printed.\n", + program_name, program_name); + vlog_usage(); + printf("\nOther Options:\n" + " -h, --help display this help message\n"); +} + +static void parse_options(int argc, char *argv[]) +{ + enum { + VLOG_OPTION_ENUMS + }; + static const struct option long_options[] = { + {"group", required_argument, NULL, 'g'}, + {"help", no_argument, NULL, 'h'}, + VLOG_LONG_OPTIONS, + {NULL, 0, NULL, 0}, + }; + char *tmp_short_options, *short_options; + int ret = EXIT_SUCCESS; + bool do_exit = false; + + tmp_short_options = ovs_cmdl_long_options_to_short_options(long_options); + short_options = xasprintf("+%s", tmp_short_options); + + while (!do_exit) { + int option; + + option = getopt_long(argc, argv, short_options, long_options, NULL); + if (option == -1) { + break; + } + + switch (option) { + + VLOG_OPTION_HANDLERS + + case 'h': + usage(); + do_exit = true; + ret = EXIT_SUCCESS; + break; + + case '?': + do_exit = true; + ret = EXIT_FAILURE; + break; + + default: + OVS_NOT_REACHED(); + } + } + + free(tmp_short_options); + free(short_options); + if (do_exit) { + exit(ret); + } +} + +static int connect_psample_socket(struct nl_sock **sock) +{ + unsigned int psample_packet_mcgroup; + int error; + + error = nl_lookup_genl_family(PSAMPLE_GENL_NAME , &psample_family); + if (error) { + VLOG_ERR("PSAMPLE_GENL_NAME not found: %s", ovs_strerror(error)); + return error; + } + + error = nl_lookup_genl_mcgroup(PSAMPLE_GENL_NAME, + PSAMPLE_NL_MCGRP_SAMPLE_NAME, + &psample_packet_mcgroup); + if (error) { + VLOG_ERR("psample packet multicast group not found: %s", + ovs_strerror(error)); + return error; + } + + error = nl_sock_create(NETLINK_GENERIC, sock); + if (error) { + VLOG_ERR("cannot create netlink socket: %s ", ovs_strerror(error)); + return error; + } + + nl_sock_listen_all_nsid(*sock, true); + + error = nl_sock_join_mcgroup(*sock, psample_packet_mcgroup); + if (error) { + nl_sock_destroy(*sock); + *sock = NULL; + VLOG_ERR("cannot join psample multicast group: %s", + ovs_strerror(error)); + return error; + } + return 0; +} + +/* Internal representation of a sample. */ +struct sample { + struct dp_packet packet; + uint32_t group_id; + uint32_t obs_domain_id; + uint32_t obs_point_id; + bool has_cookie; +}; + +static inline void +sample_clear(struct sample *sample) { + sample->group_id = 0; + sample->obs_domain_id = 0; + sample->obs_point_id = 0; + sample->has_cookie = false; + dp_packet_clear(&sample->packet); +} + +static int +parse_psample(struct ofpbuf *buf, struct sample *sample) { + static const struct nl_policy psample_packet_policy[] = { + [PSAMPLE_ATTR_SAMPLE_GROUP] = { .type = NL_A_U32 }, + [PSAMPLE_ATTR_DATA] = { .type = NL_A_UNSPEC, + .optional = true, }, + [PSAMPLE_ATTR_USER_COOKIE] = { .type = NL_A_UNSPEC, + .optional = true }, + }; + + struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size); + struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg); + struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl); + struct nlattr *attr; + + struct nlattr *a[ARRAY_SIZE(psample_packet_policy)]; + if (!nlmsg || !genl + || !nl_policy_parse(&b, 0, psample_packet_policy, a, + ARRAY_SIZE(psample_packet_policy))) { + return EINVAL; + } + + attr = a[PSAMPLE_ATTR_DATA]; + if (attr) { + dp_packet_push(&sample->packet, nl_attr_get(attr), + nl_attr_get_size(attr)); + } + + sample->group_id = nl_attr_get_u32(a[PSAMPLE_ATTR_SAMPLE_GROUP]); + + attr = a[PSAMPLE_ATTR_USER_COOKIE]; + if (attr && nl_attr_get_size(attr) == + sizeof sample->obs_domain_id + sizeof sample->obs_point_id) { + const ovs_be32 *data = nl_attr_get(attr); + + sample->has_cookie = true; + sample->obs_domain_id = ntohl(*data++); + sample->obs_point_id = ntohl(*data); + } + return 0; +} + +static void run(struct nl_sock *sock) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 10); + struct sample sample = {}; + int error; + + dp_packet_init(&sample.packet, 1500); + + fprintf(stdout, "Listening for psample events\n"); + fflush(stdout); + + for (;;) { + uint64_t buf_stub[4096 / 8]; + struct ofpbuf buf; + + sample_clear(&sample); + + ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub); + error = nl_sock_recv(sock, &buf, NULL, true); + + if (error == ENOBUFS) { + fprintf(stderr, "[missed events]\n"); + continue; + } else if (error == EAGAIN) { + continue; + } else if (error) { + VLOG_ERR_RL(&rl, "error reading samples: %i", error); + continue; + } + + error = parse_psample(&buf, &sample); + if (error) { + VLOG_ERR_RL(&rl, "error parsing samples: %i", error); + continue; + } + + if (!has_filter || sample.group_id == group_id) { + fprintf(stdout, "group_id=0x%"PRIx32" ", sample.group_id); + if (sample.has_cookie) { + fprintf(stdout, + "obs_domain=0x%"PRIx32",obs_point=0x%"PRIx32" ", + sample.obs_domain_id, sample.obs_point_id); + } + ofp_print_dp_packet(stdout, &sample.packet); + } + fflush(stdout); + } +} + +static void +test_psample_main(int argc, char *argv[]) +{ + struct nl_sock *sock; + int error; + + parse_options(argc, argv); + + if (argc - optind > 1) { + ovs_fatal(0, "at most one positional argument supported " + "(use --help for help)"); + } else if (argc - optind == 1) { + if (!str_to_uint(argv[optind], 10, &group_id)) { + ovs_fatal(0, "invalid group id"); + } + has_filter = true; + } + + error = connect_psample_socket(&sock); + if (error) { + ovs_fatal(error, "failed to connect to psample socket"); + } + + run(sock); +} + +OVSTEST_REGISTER("test-psample", test_psample_main); From patchwork Thu Jul 4 07:52:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956710 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=dFQge3XQ; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (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 4WF86C1C5zz1xpP for ; Thu, 4 Jul 2024 17:53:39 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 0FC4C40BE3; Thu, 4 Jul 2024 07:53:37 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id E9G-zgfILIT9; Thu, 4 Jul 2024 07:53:34 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org DEE7C40C0A Authentication-Results: smtp2.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=dFQge3XQ Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id DEE7C40C0A; Thu, 4 Jul 2024 07:53:28 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 958BEC0A97; Thu, 4 Jul 2024 07:53:28 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0D73FC0A9A for ; Thu, 4 Jul 2024 07:53:27 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id DB2F9410C5 for ; Thu, 4 Jul 2024 07:53:19 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id wWOkqpYLiOH3 for ; Thu, 4 Jul 2024 07:53:17 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp4.osuosl.org 1F4C2409EF Authentication-Results: smtp4.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 1F4C2409EF Authentication-Results: smtp4.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=dFQge3XQ Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp4.osuosl.org (Postfix) with ESMTPS id 1F4C2409EF for ; Thu, 4 Jul 2024 07:53:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079595; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rHs5DFvDTVb4LYRGK9h6budlgdOyY1SyhpHmGLh41mQ=; b=dFQge3XQ9agt++D/7Wyco3XDOQockYENx1VJIpJr1807E0RHXK2+7i5VsnZxYEUJBiOgzY M+kf0pXrd7rtNA8yc7d8uimlR8STH8v/TrU6zRnSCxTqmxrXNMSlFGCjsWAXEkyRIaTSAc ArJDiffwqDL7BYwXpzrybqCND5rEhcs= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-563-Nq7KI4knOuKAZNC9v5wlXw-1; Thu, 04 Jul 2024 03:53:14 -0400 X-MC-Unique: Nq7KI4knOuKAZNC9v5wlXw-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8C0B9196CDF5 for ; Thu, 4 Jul 2024 07:53:13 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 45CB81956046; Thu, 4 Jul 2024 07:53:12 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:51 +0200 Message-ID: <20240704075255.140530-11-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 10/13] tests: Test local sampling. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Test simultaneous IPFIX and local sampling including slow-path. Signed-off-by: Adrian Moreno --- tests/system-common-macros.at | 4 + tests/system-traffic.at | 285 ++++++++++++++++++++++++++++++++++ 2 files changed, 289 insertions(+) diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at index 2a68cd664..860d6a8c9 100644 --- a/tests/system-common-macros.at +++ b/tests/system-common-macros.at @@ -378,3 +378,7 @@ m4_define([OVS_CHECK_GITHUB_ACTION], # OVS_CHECK_DROP_ACTION() m4_define([OVS_CHECK_DROP_ACTION], [AT_SKIP_IF([! grep -q "Datapath supports explicit drop action" ovs-vswitchd.log])]) + +# OVS_CHECK_PSAMPLE() +m4_define([OVS_CHECK_PSAMPLE], + [AT_SKIP_IF([! grep -q "Datapath supports psample" ovs-vswitchd.log])]) diff --git a/tests/system-traffic.at b/tests/system-traffic.at index 3f1a15445..ddab4ece3 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -9103,3 +9103,288 @@ OVS_WAIT_UNTIL([ovs-pcap p2.pcap | grep -q "m4_join([], [^], OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP + +AT_BANNER([local-sampling]) + +m4_define([SAMPLE_ACTION], + [sample(probability=65535,collector_set_id=$1,obs_domain_id=$2,obs_point_id=$3)]dnl +) + +AT_SETUP([psample - sanity check]) +OVS_TRAFFIC_VSWITCHD_START() +OVS_CHECK_PSAMPLE() + +ADD_NAMESPACES(at_ns0, at_ns1) + +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \ + -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12], + [0], [ignore]) + +AT_DATA([flows.txt], [dnl +arp actions=NORMAL +in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1 +in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0 +]) + +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) + +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid]) +OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out]) + +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl +1 packets transmitted, 1 received, 0% packet loss, time 0ms +]) + +AT_CHECK([ovs-appctl dpctl/dump-flows -m --names], [0], [stdout]) +AT_CHECK([grep -q 'actions:psample(group=10,cookie=0xaa102030aa405060),ovs-p1' stdout]) +AT_CHECK([grep -q 'actions:psample(group=12,cookie=0xbb102030bb405060),ovs-p0' stdout]) + +m4_define([SAMPLE1], [m4_join([ ], + [group_id=0xa], + [obs_domain=0xaa102030,obs_point=0xaa405060], + [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])]) + +m4_define([SAMPLE2], [m4_join([ ], + [group_id=0xc], + [obs_domain=0xbb102030,obs_point=0xbb405060], + [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])]) + +OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out]) +OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out]) + +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl +Local sample statistics for bridge "br0": +Collector Set ID: 1: + Group ID : 10 + Total packets: 1 + Total bytes : 98 + +Collector Set ID: 2: + Group ID : 12 + Total packets: 1 + Total bytes : 98 +]) + +AT_CLEANUP + +AT_SETUP([psample - ipv6]) +OVS_TRAFFIC_VSWITCHD_START() +OVS_CHECK_PSAMPLE() + +ADD_NAMESPACES(at_ns0, at_ns1) + +ADD_VETH(p0, at_ns0, br0, "fc00::1/96") +ADD_VETH(p1, at_ns1, br0, "fc00::2/96") + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \ + -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12], + [0], [ignore]) + +AT_DATA([flows.txt], [dnl +priority=100,in_port=ovs-p0,ip6,icmp6,icmpv6_type=128 actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1 +priority=100,in_port=ovs-p1,ip6,icmp6,icmpv6_type=129 actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0 +priority=0 actions=NORMAL +]) + +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) + +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid]) +OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out]) + +OVS_WAIT_UNTIL_EQUAL([ip netns exec at_ns0 ping6 -I fc00::1 -q -W 2 -c 1 fc00::2 | FORMAT_PING], [dnl +1 packets transmitted, 1 received, 0% packet loss, time 0ms]) + +AT_CHECK([ovs-appctl dpctl/dump-flows -m --names], [0], [stdout]) +AT_CHECK([grep -q 'actions:psample(group=10,cookie=0xaa102030aa405060),ovs-p1' stdout]) +AT_CHECK([grep -q 'actions:psample(group=12,cookie=0xbb102030bb405060),ovs-p0' stdout]) + +m4_define([SAMPLE1], [m4_join([ ], + [group_id=0xa], + [obs_domain=0xaa102030,obs_point=0xaa405060], + [.*icmp6.*ipv6_src=fc00::1,ipv6_dst=fc00::2])]) +m4_define([SAMPLE2], [m4_join([ ], + [group_id=0xc], + [obs_domain=0xbb102030,obs_point=0xbb405060], + [.*icmp6.*ipv6_src=fc00::2,ipv6_dst=fc00::1])]) + +OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out]) +OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out]) + +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl +Local sample statistics for bridge "br0": +Collector Set ID: 1: + Group ID : 10 + Total packets: 1 + Total bytes : 118 + +Collector Set ID: 2: + Group ID : 12 + Total packets: 1 + Total bytes : 118 +]) + +AT_CLEANUP + +AT_SETUP([psample - slow]) +OVS_TRAFFIC_VSWITCHD_START() +OVS_CHECK_PSAMPLE() + +ADD_NAMESPACES(at_ns0, at_ns1) + +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \ + -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12], + [0], [ignore]) + + +AT_DATA([flows.txt], [dnl +arp actions=NORMAL +in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1 +in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0 +]) +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) + +AT_CHECK([ovs-appctl ofproto/trace br0 \ + 'in_port=ovs-p0,dl_src=e4:11:22:33:44:55,dl_dst=e4:11:22:33:44:66,dl_type=0x0800,nw_src=10.1.1.1,nw_dst=10.1.1.12'], + [0], [stdout]) + +AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: psample(group=10,cookie=0xaa102030aa405060),3 +]) + +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid]) + +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl +1 packets transmitted, 1 received, 0% packet loss, time 0ms +]) + +m4_define([SAMPLE1], [m4_join([ ], + [group_id=0xa], + [obs_domain=0xaa102030,obs_point=0xaa405060], + [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])]) + +m4_define([SAMPLE2], [m4_join([ ], + [group_id=0xc], + [obs_domain=0xbb102030,obs_point=0xbb405060], + [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])]) + +AT_CHECK([grep -qE 'SAMPLE1' psample.out]) +AT_CHECK([grep -qE 'SAMPLE2' psample.out]) + +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl +Local sample statistics for bridge "br0": +Collector Set ID: 1: + Group ID : 10 + Total packets: 1 + Total bytes : 98 + +Collector Set ID: 2: + Group ID : 12 + Total packets: 1 + Total bytes : 98 +]) + +OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"]) +AT_CLEANUP + +AT_SETUP([psample - with IPFIX]) +OVS_TRAFFIC_VSWITCHD_START() +OVS_CHECK_PSAMPLE() + +ADD_NAMESPACES(at_ns0, at_ns1) + +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- --id=@i create IPFIX targets=\"127.0.0.1:4739\" \ + -- create Flow_Sample_Collector_Set id=1 ipfix=@i bridge=@br0 local_group_id=10 \ + -- create Flow_Sample_Collector_Set id=2 ipfix=@i bridge=@br0 local_group_id=12], + [0], [ignore]) + +AT_DATA([flows.txt], [dnl +arp actions=NORMAL +in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1 +in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0 +]) + +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) + + +AT_CHECK([ovs-appctl ofproto/trace br0 \ + 'in_port=ovs-p0,dl_src=e4:11:22:33:44:55,dl_dst=e4:11:22:33:44:66,dl_type=0x0800,nw_src=10.1.1.1,nw_dst=10.1.1.12'], + [0], [stdout]) + + +m4_define([ACTIONS], [m4_join([], + [psample(group=10,cookie=0xaa102030aa405060),], + [userspace(pid=4294967295,], + [flow_sample(probability=65535,], + [collector_set_id=1,], + [obs_domain_id=2853183536,], + [obs_point_id=2856341600,], + [output_port=4294967295)),], + [3])]) + +AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: ACTIONS +]) + +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid]) +OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out]) + +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl +1 packets transmitted, 1 received, 0% packet loss, time 0ms +]) + +m4_define([SAMPLE1], [m4_join([ ], + [group_id=0xa], + [obs_domain=0xaa102030,obs_point=0xaa405060], + [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])]) + +m4_define([SAMPLE2], [m4_join([ ], + [group_id=0xc], + [obs_domain=0xbb102030,obs_point=0xbb405060], + [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])]) + +OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out]) +OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out]) + +dnl Check IPFIX samples have been received. +dnl Entries can be unsorted and IFPIX packets might not have been sent (or +dnl at least tried to be sent) yet. +OVS_WAIT_UNTIL_EQUAL([ovs-ofctl dump-ipfix-flow br0 | \ + sed 's/tx pkts=[[0-9]]*/tx pkts=24/' | \ + sed 's/tx errs=[[0-9]]*/tx errs=0/' | \ + sed 's/id [[1-2]]:/id ?:/'], [dnl +NXST_IPFIX_FLOW reply (xid=0x2): 2 ids + id ?: flows=1, current flows=0, sampled pkts=1, ipv4 ok=1, ipv6 ok=0, tx pkts=24 + pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0 + id ?: flows=1, current flows=0, sampled pkts=1, ipv4 ok=1, ipv6 ok=0, tx pkts=24 + pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0]) + +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl +Local sample statistics for bridge "br0": +Collector Set ID: 1: + Group ID : 10 + Total packets: 1 + Total bytes : 98 + +Collector Set ID: 2: + Group ID : 12 + Total packets: 1 + Total bytes : 98 +]) + +dnl OVS will fail to send IPFIX packets because the target is localhost +dnl and the port is closed. Ignore the message it generates. +OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"]) +AT_CLEANUP From patchwork Thu Jul 4 07:52:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956711 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=fDktGfjl; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::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 4WF86C6g72z1xqs for ; Thu, 4 Jul 2024 17:53:39 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 3CD254109F; Thu, 4 Jul 2024 07:53:38 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id uhS_dg0j1DRX; Thu, 4 Jul 2024 07:53:34 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 0B19940752 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=fDktGfjl Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id 0B19940752; Thu, 4 Jul 2024 07:53:32 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id AA484C0A97; Thu, 4 Jul 2024 07:53:31 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0FF6EC0A9A for ; Thu, 4 Jul 2024 07:53:30 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id D9EB8410D6 for ; Thu, 4 Jul 2024 07:53:20 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id U8vI1JA3rEEA for ; Thu, 4 Jul 2024 07:53:18 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp4.osuosl.org 3B83D40BFB Authentication-Results: smtp4.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 3B83D40BFB Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp4.osuosl.org (Postfix) with ESMTPS id 3B83D40BFB for ; Thu, 4 Jul 2024 07:53:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079597; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bF3iAmYrew+LVEw1f+/WMiGkOiNuvbtRl0PyDZgoe+Q=; b=fDktGfjl/OiusItpxuf5QXqa1WpIfJYIUqZ7uBxaZlFLrL+RRgy0pmwdkhHf6B+q7rxDEV yLz/jk2ibhpGwtXcOlX5K7XRAdFV1rKVy3FXw7bkvPY2Vi3+vO4ujDJod/0EU6p6coOwvq l7lRLK1k07SQK6duzXA2kTWMjDhU0IE= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-230-gq6-gNYvMhO1ejo1_R7HuA-1; Thu, 04 Jul 2024 03:53:15 -0400 X-MC-Unique: gq6-gNYvMhO1ejo1_R7HuA-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CBC86195419C for ; Thu, 4 Jul 2024 07:53:14 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C45B51956046; Thu, 4 Jul 2024 07:53:13 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:52 +0200 Message-ID: <20240704075255.140530-12-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 11/13] ofproto: xlate: Make flow-sampled drops explicit. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" When an action set ends in a an OFP_SAMPLE action, it means the packet will be dropped and sampled. Make the drop explicit in this case so that drop statistics remain accurate. This could be done outside of the sample action, i.e: "sample(...),drop" but datapaths optimize sample actions that are found in the last position. So, taking into account that datapaths already report when the last sample probability fails, it is safe to put the drop inside the sample, i.e: "sample(...,drop)". Signed-off-by: Adrian Moreno --- ofproto/ofproto-dpif-xlate.c | 16 +++++++-- tests/drop-stats.at | 65 ++++++++++++++++++++++++++++++++++++ tests/ofproto-dpif.at | 44 ++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index b9546dc5b..094fe5d72 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -715,6 +715,7 @@ static void xlate_xbundle_copy(struct xbridge *, struct xbundle *); static void xlate_xport_copy(struct xbridge *, struct xbundle *, struct xport *); static void xlate_xcfg_free(struct xlate_cfg *); +static void put_drop_action(struct ofpbuf *, enum xlate_error); /* Tracing helpers. */ @@ -3392,6 +3393,8 @@ struct sample_userspace_args { struct compose_sample_args { uint32_t probability; /* Number of packets out of * UINT32_MAX to sample. */ + bool last; /* If it's the last action and a + * drop action must be added. */ struct sample_userspace_args *userspace; /* Optional, * arguments for userspace. */ struct sample_psample_args *psample; /* Optional, @@ -3456,6 +3459,11 @@ compose_sample_action(struct xlate_ctx *ctx, ovs_assert(res == 0); } + if (args->last && + ovs_explicit_drop_action_supported(ctx->xbridge->ofproto)) { + put_drop_action(ctx->odp_actions, ctx->error); + } + if (is_sample) { nl_msg_end_nested(ctx->odp_actions, actions_offset); nl_msg_end_nested(ctx->odp_actions, sample_offset); @@ -3490,6 +3498,7 @@ compose_sflow_action(struct xlate_ctx *ctx) args.probability = dpif_sflow_get_probability(sflow); args.userspace = &userspace; + args.last = false; return compose_sample_action(ctx, &args); } @@ -3542,6 +3551,7 @@ compose_ipfix_action(struct xlate_ctx *ctx, odp_port_t output_odp_port) args.probability = dpif_ipfix_get_bridge_exporter_probability(ipfix); args.userspace = &userspace; + args.last = false; compose_sample_action(ctx, &args); } @@ -5974,7 +5984,8 @@ xlate_fill_ipfix_sample(struct xlate_ctx *ctx, static void xlate_sample_action(struct xlate_ctx *ctx, - const struct ofpact_sample *os) + const struct ofpact_sample *os, + bool last) { uint8_t cookie_buf[sizeof(os->obs_domain_id) + sizeof(os->obs_point_id)]; struct dpif_lsample *lsample = ctx->xbridge->lsample; @@ -5991,6 +6002,7 @@ xlate_sample_action(struct xlate_ctx *ctx, * the same percentage. */ compose_args.probability = ((uint32_t) os->probability << 16) | os->probability; + compose_args.last = last; if (ipfix) { xlate_fill_ipfix_sample(ctx, os, ipfix, &userspace); @@ -7726,7 +7738,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_SAMPLE: - xlate_sample_action(ctx, ofpact_get_SAMPLE(a)); + xlate_sample_action(ctx, ofpact_get_SAMPLE(a), last); break; case OFPACT_CLONE: diff --git a/tests/drop-stats.at b/tests/drop-stats.at index 1d3af98da..44c5cc35b 100644 --- a/tests/drop-stats.at +++ b/tests/drop-stats.at @@ -191,3 +191,68 @@ ovs-appctl coverage/read-counter drop_action_too_many_mpls_labels OVS_VSWITCHD_STOP(["/|WARN|/d"]) AT_CLEANUP + +AT_SETUP([drop-stats - sampling action]) + +OVS_VSWITCHD_START([dnl + set bridge br0 datapath_type=dummy \ + protocols=OpenFlow10,OpenFlow13,OpenFlow14,OpenFlow15 -- \ + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \ + add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2]) + +AT_DATA([flows.txt], [dnl +table=0,in_port=1,actions=sample(probability=65535,collector_set_id=1) +table=0,in_port=2,actions=sample(probability=32767,collector_set_id=1) +]) + +AT_CHECK([ + ovs-ofctl del-flows br0 + ovs-ofctl -Oopenflow13 add-flows br0 flows.txt +]) + +AT_CHECK([ovs-vsctl --id=@br0 get Bridge br0 \ + -- --id=@ipfix create IPFIX targets=\"127.0.0.1:4739\" \ + -- create Flow_Sample_Collector_Set id=1 bridge=@br0 ipfix=@ipfix], + [0], [ignore]) + +AT_CHECK([ + ovs-appctl netdev-dummy/receive p1 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' +], [0], [ignore]) + +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/used:[[0-9]].[[0-9]]*s/used:0.0/' | sort], [0], [flow-dump from the main thread: +recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:212, used:0.0, actions:userspace(pid=0,flow_sample(probability=65535,collector_set_id=1,obs_domain_id=0,obs_point_id=0,output_port=4294967295)),drop +]) + +ovs-appctl time/warp 5000 + +AT_CHECK([ +ovs-appctl coverage/read-counter drop_action_of_pipeline +], [0], [dnl +3 +]) + +AT_CHECK([ovs-appctl dpctl/del-flows]) + +AT_CHECK([ + ovs-appctl netdev-dummy/receive p2 'in_port(2),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' + ovs-appctl netdev-dummy/receive p2 'in_port(2),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' + ovs-appctl netdev-dummy/receive p2 'in_port(2),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' +], [0], [ignore]) + +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/used:[[0-9]].[[0-9]]*s/used:0.0/' | sort], [0], [flow-dump from the main thread: +recirc_id(0),in_port(2),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:212, used:0.0, actions:sample(sample=50.0%,actions(userspace(pid=0,flow_sample(probability=32767,collector_set_id=1,obs_domain_id=0,obs_point_id=0,output_port=4294967295)),drop)) +]) + +ovs-appctl time/warp 5000 + +AT_CHECK([ovs-appctl coverage/read-counter drop_action_of_pipeline > explicit_drops]) +AT_CHECK([ovs-appctl coverage/read-counter datapath_drop_sample_error > sample_drops]) + +AT_CHECK([expr $(cat sample_drops) + $(cat explicit_drops)], [0], [dnl +6 +]) + +OVS_VSWITCHD_STOP(["/sending to collector failed/d"]) +AT_CLEANUP diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index 2a04977a7..701b8a851 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -12282,3 +12282,47 @@ Datapath actions: EXPECTED_ACT OVS_VSWITCHD_STOP() AT_CLEANUP + +AT_SETUP([ofproto-dpif - Local sampling - drop]) +OVS_VSWITCHD_START +add_of_ports br0 1 2 + +AT_CHECK([ovs-appctl dpif/set-dp-features --force br0 psample true], [0], [ignore]) + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=42], + [0], [ignore]) + +AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=slowpath pktps stats bands=type=drop rate=2']) + +AT_DATA([flows.txt], [dnl +in_port=1, actions=sample(probability=32767,collector_set_id=1,obs_domain_id=100,obs_point_id=200) +in_port=2, actions=sample(probability=65535,collector_set_id=1,obs_domain_id=100,obs_point_id=200) +]) + +AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt]) + +m4_define([TRACE_PKT], [m4_join([,], + [eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)], + [ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no)], + [icmp(type=8,code=0)])]) + +m4_define([EXPECTED_ACT1], [m4_join([], + [sample(sample=50.0%,actions(], + [psample(group=42,cookie=0x64000000c8),], + [drop], + [))], +)]) + +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1) TRACE_PKT'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: EXPECTED_ACT1 +]) + +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2) TRACE_PKT'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: psample(group=42,cookie=0x64000000c8),drop +]) + +OVS_VSWITCHD_STOP() +AT_CLEANUP From patchwork Thu Jul 4 07:52:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956713 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=d7yM7HZR; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (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 4WF86t16K7z1xpP for ; Thu, 4 Jul 2024 17:54:14 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 3193F60B60; Thu, 4 Jul 2024 07:54:12 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id ExFuSWsDKWUh; Thu, 4 Jul 2024 07:54:04 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 8A06460B66 Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=d7yM7HZR Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id 8A06460B66; Thu, 4 Jul 2024 07:53:56 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 46E99C0A97; Thu, 4 Jul 2024 07:53:56 +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 14327C0A97 for ; Thu, 4 Jul 2024 07:53:55 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 0792C8485C for ; Thu, 4 Jul 2024 07:53:31 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id rxXzAVgxdhNT for ; Thu, 4 Jul 2024 07:53:28 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org BA7F184806 Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org BA7F184806 Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=d7yM7HZR Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id BA7F184806 for ; Thu, 4 Jul 2024 07:53:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079601; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OtODsAiBdiYh9S27WoVLWMm0+zkVvh4qJ8bLJFEkn8Q=; b=d7yM7HZRt1Yx57aMpR2U741eucE6wJNAtimoJtI1/wFnP75q/5C+NLAnyPqlmtd9FvsOWU YHhGZ+wZzcDB2F7dyiMnkrirZbu1/kOJFUONVQCJ86NM6cYotj5pMHJFqxrsy7gslldBCP 0q7vqVQMsrowgA8k7G+CcoVKwNq6OII= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-45-k7XR-aUfNkegEUYuVoyudg-1; Thu, 04 Jul 2024 03:53:17 -0400 X-MC-Unique: k7XR-aUfNkegEUYuVoyudg-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BEA8719560A3; Thu, 4 Jul 2024 07:53:16 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 437431955F65; Thu, 4 Jul 2024 07:53:15 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:53 +0200 Message-ID: <20240704075255.140530-13-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 12/13] ofproto: xlate: Make bridge-sampled drops explicit. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: anju.thomas@ericsson.com Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" The decision to add or not the explicit drop action is currently based on whether the resulting dp action list is empty or not. This is OK for most of the cases but if per-flow IPFIX/sFlow sampling is enabled on the bridge, it doesn't work as expected. Fix this by taking into account the size of these sampling actions. Fixes: a13a0209750c ("userspace: Improved packet drop statistics.") Cc: anju.thomas@ericsson.com Signed-off-by: Adrian Moreno --- ofproto/ofproto-dpif-xlate.c | 5 ++-- tests/drop-stats.at | 44 ++++++++++++++++++++++++++++++++++++ tests/ofproto-dpif.at | 4 ++-- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 094fe5d72..323a58cbf 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -8153,6 +8153,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) uint64_t action_set_stub[1024 / 8]; uint64_t frozen_actions_stub[1024 / 8]; uint64_t actions_stub[256 / 8]; + size_t sample_actions_len = 0; struct ofpbuf scratch_actions = OFPBUF_STUB_INITIALIZER(actions_stub); struct xlate_ctx ctx = { .xin = xin, @@ -8412,7 +8413,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) user_cookie_offset = compose_sflow_action(&ctx); compose_ipfix_action(&ctx, ODPP_NONE); } - size_t sample_actions_len = ctx.odp_actions->size; + sample_actions_len = ctx.odp_actions->size; bool ecn_drop = !tnl_process_ecn(flow); if (!ecn_drop @@ -8575,7 +8576,7 @@ exit: } /* Install drop action if datapath supports explicit drop action. */ - if (xin->odp_actions && !xin->odp_actions->size && + if (xin->odp_actions && xin->odp_actions->size == sample_actions_len && ovs_explicit_drop_action_supported(ctx.xbridge->ofproto)) { put_drop_action(xin->odp_actions, ctx.error); } diff --git a/tests/drop-stats.at b/tests/drop-stats.at index 44c5cc35b..31782ac52 100644 --- a/tests/drop-stats.at +++ b/tests/drop-stats.at @@ -192,6 +192,50 @@ ovs-appctl coverage/read-counter drop_action_too_many_mpls_labels OVS_VSWITCHD_STOP(["/|WARN|/d"]) AT_CLEANUP +AT_SETUP([drop-stats - sampling]) + +OVS_VSWITCHD_START([dnl + set bridge br0 datapath_type=dummy \ + protocols=OpenFlow10,OpenFlow13,OpenFlow14,OpenFlow15 -- \ + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1]) + +AT_DATA([flows.txt], [dnl +table=0,in_port=1,actions=drop +]) + +AT_CHECK([ + ovs-ofctl del-flows br0 + ovs-ofctl -Oopenflow13 add-flows br0 flows.txt + ovs-ofctl -Oopenflow13 dump-flows br0 | ofctl_strip | sort | grep actions ], [0], [dnl + in_port=1 actions=drop +]) + +AT_CHECK([ovs-vsctl -- set bridge br0 ipfix=@fix -- \ + --id=@fix create ipfix targets=\"127.0.0.1:4739\" \ + sampling=1], + [0], [ignore]) + +AT_CHECK([ + ovs-appctl netdev-dummy/receive p1 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' +], [0], [ignore]) + +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/used:[[0-9]].[[0-9]]*s/used:0.0/' | sort], [0], [flow-dump from the main thread: +recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:212, used:0.0, actions:userspace(pid=0,ipfix(output_port=4294967295)),drop +]) + +ovs-appctl time/warp 5000 + +AT_CHECK([ +ovs-appctl coverage/read-counter drop_action_of_pipeline +], [0], [dnl +3 +]) + +OVS_VSWITCHD_STOP(["/sending to collector failed/d"]) + +AT_CLEANUP AT_SETUP([drop-stats - sampling action]) OVS_VSWITCHD_START([dnl diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index 701b8a851..ba8f3b69c 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -8082,7 +8082,7 @@ for i in `seq 1 3`; do done AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl flow-dump from the main thread: -packets:2, bytes:68, used:0.001s, actions:userspace(pid=0,ipfix(output_port=4294967295)) +packets:2, bytes:68, used:0.001s, actions:userspace(pid=0,ipfix(output_port=4294967295)),drop ]) AT_CHECK([ovs-appctl revalidator/purge]) @@ -8118,7 +8118,7 @@ for i in `seq 1 3`; do done AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl flow-dump from the main thread: -packets:2, bytes:68, used:0.001s, actions:sample(sample=100.0%,actions(meter(0),userspace(pid=0,ipfix(output_port=4294967295)))) +packets:2, bytes:68, used:0.001s, actions:sample(sample=100.0%,actions(meter(0),userspace(pid=0,ipfix(output_port=4294967295)))),drop ]) dnl Remove the IPFIX configuration. From patchwork Thu Jul 4 07:52:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Adri=C3=A1n_Moreno?= X-Patchwork-Id: 1956714 X-Patchwork-Delegate: horms@verge.net.au 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=WtqWRVR8; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (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 4WF87V3kShz1xqs for ; Thu, 4 Jul 2024 17:54:46 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id E8FF0611A3; Thu, 4 Jul 2024 07:54:44 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id pVl3jpuEQCWs; Thu, 4 Jul 2024 07:54:43 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 0179F6066C Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=WtqWRVR8 Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id 0179F6066C; Thu, 4 Jul 2024 07:54:43 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id C7D42C0A97; Thu, 4 Jul 2024 07:54:42 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 18F24C0A97 for ; Thu, 4 Jul 2024 07:54:42 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id F389D8480E for ; Thu, 4 Jul 2024 07:53:41 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id Edsgo9iTk9VS for ; Thu, 4 Jul 2024 07:53:38 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amorenoz@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org AA11A84830 Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org AA11A84830 Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=WtqWRVR8 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id AA11A84830 for ; Thu, 4 Jul 2024 07:53:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720079605; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WzjXecpEq7o3LQGkefpyKPq96nFDHgDqDk4aS4jShv4=; b=WtqWRVR8xstdcj7ZRo7rYxPzxW9928JDGvPwGAHCqXdfWNzFE2zcib8VnFVcT2ObfQA0s1 bFIEB7kzNu73zSDfdg5VSHevC7lYcmxABJQvF8+gerJQrO0loCQ3vS9ONXDDi1e28LDK7p +h4yq8VnWcDDus5H3X11LNwqjdqK3+w= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-296-nBepquyHN9yuOApQ_EAgmw-1; Thu, 04 Jul 2024 03:53:19 -0400 X-MC-Unique: nBepquyHN9yuOApQ_EAgmw-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 76D7D1955F42 for ; Thu, 4 Jul 2024 07:53:18 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.194.59]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 30FD11956046; Thu, 4 Jul 2024 07:53:16 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Thu, 4 Jul 2024 09:52:54 +0200 Message-ID: <20240704075255.140530-14-amorenoz@redhat.com> In-Reply-To: <20240704075255.140530-1-amorenoz@redhat.com> References: <20240704075255.140530-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH v3 13/13] ofp-actions: Load data from fields in sample action. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" When sample action gets used as a way of sampling traffic with controller-generated metadata (i.e: obs_domain_id and obs_point_id), the controller will have to increase the number of flows to ensure each part of the pipeline contains the right metadata. As an example, if the controller decides to sample stateful traffic, it could store the computed metadata for each connection in the conntrack label. However, for established connections, a flow must be created for each different ct_label value with a sample action that contains a different hardcoded obs_domain and obs_point id. This patch adds a new version of the NXAST_RAW_SAMPLE* action (number 4) that supports specifying the observation point and domain using an OpenFlow field reference, so now the controller can express: sample(... obs_domain_id=NXM_NX_CT_LABEL[0..31], obs_point_id=NXM_NX_CT_LABEL[32..63] ... ) Signed-off-by: Adrian Moreno --- include/openvswitch/ofp-actions.h | 8 +- lib/ofp-actions.c | 249 +++++++++++++++++++++++++++--- ofproto/ofproto-dpif-xlate.c | 55 ++++++- python/ovs/flow/ofp.py | 8 +- python/ovs/flow/ofp_act.py | 4 +- tests/ofp-actions.at | 5 + tests/system-traffic.at | 74 +++++++++ 7 files changed, 364 insertions(+), 39 deletions(-) diff --git a/include/openvswitch/ofp-actions.h b/include/openvswitch/ofp-actions.h index 7b57e49ad..56dc2c147 100644 --- a/include/openvswitch/ofp-actions.h +++ b/include/openvswitch/ofp-actions.h @@ -1015,14 +1015,16 @@ enum nx_action_sample_direction { /* OFPACT_SAMPLE. * - * Used for NXAST_SAMPLE, NXAST_SAMPLE2, and NXAST_SAMPLE3. */ + * Used for NXAST_SAMPLE, NXAST_SAMPLE2, NXAST_SAMPLE3 and NXAST_SAMPLE4. */ struct ofpact_sample { OFPACT_PADDED_MEMBERS( struct ofpact ofpact; uint16_t probability; /* Always positive. */ uint32_t collector_set_id; - uint32_t obs_domain_id; - uint32_t obs_point_id; + uint32_t obs_domain_imm; + struct mf_subfield obs_domain_src; + uint32_t obs_point_imm; + struct mf_subfield obs_point_src; ofp_port_t sampling_port; enum nx_action_sample_direction direction; ); diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index da7b1dd31..e329a7e3f 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -330,6 +330,8 @@ enum ofp_raw_action_type { NXAST_RAW_SAMPLE2, /* NX1.0+(41): struct nx_action_sample2. */ NXAST_RAW_SAMPLE3, + /* NX1.0+(51): struct nx_action_sample4, ... VLMFF */ + NXAST_RAW_SAMPLE4, /* NX1.0+(34): struct nx_action_conjunction. */ NXAST_RAW_CONJUNCTION, @@ -6188,6 +6190,34 @@ struct nx_action_sample2 { }; OFP_ASSERT(sizeof(struct nx_action_sample2) == 32); +/* Action structure for NXAST_SAMPLE4 + * + * NXAST_SAMPLE4 was added in Open vSwitch 3.4.0. Compared to NXAST_SAMPLE3, + * it adds support for using field specifiers for observation_domain_id and + * observation_point_id. */ +struct nx_action_sample4 { + ovs_be16 type; /* OFPAT_VENDOR. */ + ovs_be16 len; /* Length is 32. */ + ovs_be32 vendor; /* NX_VENDOR_ID. */ + ovs_be16 subtype; /* NXAST_SAMPLE. */ + ovs_be16 probability; /* Fraction of packets to sample. */ + ovs_be32 collector_set_id; /* ID of collector set in OVSDB. */ + ovs_be32 obs_domain_src; /* Source of the observation_domain_id. */ + union { + ovs_be16 obs_domain_ofs_nbits; /* Range to use from source field. */ + ovs_be32 obs_domain_imm; /* Immediate value for domain id. */ + }; + ovs_be32 obs_point_src; /* Source of the observation_point_id */ + union { + ovs_be16 obs_point_ofs_nbits; /* Range to use from source field. */ + ovs_be32 obs_point_imm; /* Immediate value for point id. */ + }; + ovs_be16 sampling_port; /* Sampling port. */ + uint8_t direction; /* Sampling direction. */ + uint8_t zeros[5]; /* Pad to a multiple of 8 bytes */ + }; + OFP_ASSERT(sizeof(struct nx_action_sample4) == 40); + static enum ofperr decode_NXAST_RAW_SAMPLE(const struct nx_action_sample *nas, enum ofp_version ofp_version OVS_UNUSED, @@ -6199,11 +6229,14 @@ decode_NXAST_RAW_SAMPLE(const struct nx_action_sample *nas, sample->ofpact.raw = NXAST_RAW_SAMPLE; sample->probability = ntohs(nas->probability); sample->collector_set_id = ntohl(nas->collector_set_id); - sample->obs_domain_id = ntohl(nas->obs_domain_id); - sample->obs_point_id = ntohl(nas->obs_point_id); + sample->obs_domain_imm = ntohl(nas->obs_domain_id); + sample->obs_domain_src.field = NULL; + sample->obs_point_imm = ntohl(nas->obs_point_id); + sample->obs_point_src.field = NULL; sample->sampling_port = OFPP_NONE; sample->direction = NX_ACTION_SAMPLE_DEFAULT; - + sample->obs_domain_src.field = NULL; + sample->obs_point_src.field = NULL; if (sample->probability == 0) { return OFPERR_OFPBAC_BAD_ARGUMENT; } @@ -6220,8 +6253,10 @@ decode_SAMPLE2(const struct nx_action_sample2 *nas, sample->ofpact.raw = raw; sample->probability = ntohs(nas->probability); sample->collector_set_id = ntohl(nas->collector_set_id); - sample->obs_domain_id = ntohl(nas->obs_domain_id); - sample->obs_point_id = ntohl(nas->obs_point_id); + sample->obs_domain_imm = ntohl(nas->obs_domain_id); + sample->obs_domain_src.field = NULL; + sample->obs_point_imm = ntohl(nas->obs_point_id); + sample->obs_point_src.field = NULL; sample->sampling_port = u16_to_ofp(ntohs(nas->sampling_port)); sample->direction = direction; @@ -6241,41 +6276,174 @@ decode_NXAST_RAW_SAMPLE2(const struct nx_action_sample2 *nas, ofpact_put_SAMPLE(out)); } +static int +check_sample_direction(enum nx_action_sample_direction direction) +{ + if (direction != NX_ACTION_SAMPLE_DEFAULT && + direction != NX_ACTION_SAMPLE_INGRESS && + direction != NX_ACTION_SAMPLE_EGRESS) { + VLOG_WARN_RL(&rl, "invalid sample direction %"PRIu8, direction); + return OFPERR_OFPBAC_BAD_ARGUMENT; + } + return 0; +} static enum ofperr decode_NXAST_RAW_SAMPLE3(const struct nx_action_sample2 *nas, enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out) { struct ofpact_sample *sample = ofpact_put_SAMPLE(out); + int err; + if (!is_all_zeros(nas->zeros, sizeof nas->zeros)) { return OFPERR_NXBRC_MUST_BE_ZERO; } - if (nas->direction != NX_ACTION_SAMPLE_DEFAULT && - nas->direction != NX_ACTION_SAMPLE_INGRESS && - nas->direction != NX_ACTION_SAMPLE_EGRESS) { - VLOG_WARN_RL(&rl, "invalid sample direction %"PRIu8, nas->direction); - return OFPERR_OFPBAC_BAD_ARGUMENT; + err = check_sample_direction(nas->direction); + if (err) { + return err; } return decode_SAMPLE2(nas, NXAST_RAW_SAMPLE3, nas->direction, sample); } +static int +decode_sample_obs_id(ovs_be32 src, ovs_be16 ofs_nbits, ovs_be32 imm, + const struct vl_mff_map *vl_mff_map, uint64_t *tlv_bitmap, + struct mf_subfield *src_out, uint32_t *imm_out) +{ + if (src) { + enum ofperr error; + + src_out->ofs = nxm_decode_ofs(ofs_nbits); + src_out->n_bits = nxm_decode_n_bits(ofs_nbits); + error = mf_vl_mff_mf_from_nxm_header(ntohl(src), + vl_mff_map, &src_out->field, + tlv_bitmap); + if (error) { + return error; + } + + error = mf_check_src(src_out, NULL); + if (error) { + return error; + } + + if (src_out->n_bits != 32) { + VLOG_WARN_RL(&rl, "field associated to sample observation id is " + "not 32-bit but %d", src_out->n_bits); + return OFPERR_OFPBAC_BAD_SET_LEN; + } + } else { + src_out->field = NULL; + *imm_out = ntohl(imm); + } + + return 0; +} + +static enum ofperr +decode_NXAST_RAW_SAMPLE4(const struct nx_action_sample4 *nas, + enum ofp_version ofp_version OVS_UNUSED, + const struct vl_mff_map *vl_mff_map, + uint64_t *tlv_bitmap, + struct ofpbuf *out) +{ + struct ofpact_sample *sample = ofpact_put_SAMPLE(out); + int err; + + if (!is_all_zeros(nas->zeros, sizeof nas->zeros)) { + return OFPERR_NXBRC_MUST_BE_ZERO; + } + + err = check_sample_direction(nas->direction); + if (err) { + return err; + } + + sample->ofpact.raw = NXAST_RAW_SAMPLE4; + sample->probability = ntohs(nas->probability); + sample->collector_set_id = ntohl(nas->collector_set_id); + sample->sampling_port = u16_to_ofp(ntohs(nas->sampling_port)); + sample->direction = nas->direction; + + if (sample->probability == 0) { + return OFPERR_OFPBAC_BAD_ARGUMENT; + } + + err = decode_sample_obs_id(nas->obs_domain_src, + nas->obs_domain_ofs_nbits, + nas->obs_domain_imm, + vl_mff_map, tlv_bitmap, + &sample->obs_domain_src, + &sample->obs_domain_imm); + if (err) { + return err; + } + + err = decode_sample_obs_id(nas->obs_point_src, + nas->obs_point_ofs_nbits, + nas->obs_point_imm, + vl_mff_map, tlv_bitmap, + &sample->obs_point_src, + &sample->obs_point_imm); + if (err) { + return err; + } + + return 0; +} + static void encode_SAMPLE2(const struct ofpact_sample *sample, struct nx_action_sample2 *nas) { nas->probability = htons(sample->probability); nas->collector_set_id = htonl(sample->collector_set_id); - nas->obs_domain_id = htonl(sample->obs_domain_id); - nas->obs_point_id = htonl(sample->obs_point_id); + nas->obs_domain_id = htonl(sample->obs_domain_imm); + nas->obs_point_id = htonl(sample->obs_point_imm); + nas->sampling_port = htons(ofp_to_u16(sample->sampling_port)); + nas->direction = sample->direction; +} + +static void +encode_SAMPLE4(const struct ofpact_sample *sample, + struct nx_action_sample4 *nas) +{ + nas->probability = htons(sample->probability); + nas->collector_set_id = htonl(sample->collector_set_id); nas->sampling_port = htons(ofp_to_u16(sample->sampling_port)); nas->direction = sample->direction; + + if (sample->obs_domain_src.field) { + nas->obs_domain_src = + htonl(nxm_header_from_mff(sample->obs_domain_src.field)); + nas->obs_domain_ofs_nbits = + nxm_encode_ofs_nbits(sample->obs_domain_src.ofs, + sample->obs_domain_src.n_bits); + } else { + nas->obs_domain_src = htonl(0); + nas->obs_domain_imm = htonl(sample->obs_domain_imm); + } + if (sample->obs_point_src.field) { + nas->obs_point_src = + htonl(nxm_header_from_mff(sample->obs_point_src.field)); + nas->obs_point_ofs_nbits = + nxm_encode_ofs_nbits(sample->obs_point_src.ofs, + sample->obs_point_src.n_bits); + } else { + nas->obs_point_src = htonl(0); + nas->obs_point_imm = htonl(sample->obs_point_imm); + } } static void encode_SAMPLE(const struct ofpact_sample *sample, enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out) { - if (sample->ofpact.raw == NXAST_RAW_SAMPLE3 + if (sample->ofpact.raw == NXAST_RAW_SAMPLE4 || + sample->obs_domain_src.field || + sample->obs_point_src.field) { + encode_SAMPLE4(sample, put_NXAST_SAMPLE4(out)); + } else if (sample->ofpact.raw == NXAST_RAW_SAMPLE3 || sample->direction != NX_ACTION_SAMPLE_DEFAULT) { encode_SAMPLE2(sample, put_NXAST_SAMPLE3(out)); } else if (sample->ofpact.raw == NXAST_RAW_SAMPLE2 @@ -6285,8 +6453,8 @@ encode_SAMPLE(const struct ofpact_sample *sample, struct nx_action_sample *nas = put_NXAST_SAMPLE(out); nas->probability = htons(sample->probability); nas->collector_set_id = htonl(sample->collector_set_id); - nas->obs_domain_id = htonl(sample->obs_domain_id); - nas->obs_point_id = htonl(sample->obs_point_id); + nas->obs_domain_id = htonl(sample->obs_domain_imm); + nas->obs_point_id = htonl(sample->obs_point_imm); } } @@ -6314,9 +6482,35 @@ parse_SAMPLE(char *arg, const struct ofpact_parse_params *pp) } else if (!strcmp(key, "collector_set_id")) { error = str_to_u32(value, &os->collector_set_id); } else if (!strcmp(key, "obs_domain_id")) { - error = str_to_u32(value, &os->obs_domain_id); + error = str_to_u32(value, &os->obs_domain_imm); + + if (error) { + free(error); + error = mf_parse_subfield(&os->obs_domain_src, value); + if (error) { + return error; + } + if (os->obs_domain_src.n_bits != 32) { + error = xasprintf("invalid length of obs_domain_id field " + "(%d). Must be 32", + os->obs_domain_src.n_bits); + } + } } else if (!strcmp(key, "obs_point_id")) { - error = str_to_u32(value, &os->obs_point_id); + error = str_to_u32(value, &os->obs_point_imm); + + if (error) { + free(error); + error = mf_parse_subfield(&os->obs_point_src, value); + if (error) { + return error; + } + if (os->obs_point_src.n_bits != 32) { + error = xasprintf("invalid length of obs_point_id field " + "(%d). Must be 32", + os->obs_point_src.n_bits); + } + } } else if (!strcmp(key, "sampling_port")) { if (!ofputil_port_from_string(value, pp->port_map, &os->sampling_port)) { @@ -6346,14 +6540,23 @@ format_SAMPLE(const struct ofpact_sample *a, const struct ofpact_format_params *fp) { ds_put_format(fp->s, "%ssample(%s%sprobability=%s%"PRIu16 - ",%scollector_set_id=%s%"PRIu32 - ",%sobs_domain_id=%s%"PRIu32 - ",%sobs_point_id=%s%"PRIu32, + ",%scollector_set_id=%s%"PRIu32, colors.paren, colors.end, colors.param, colors.end, a->probability, - colors.param, colors.end, a->collector_set_id, - colors.param, colors.end, a->obs_domain_id, - colors.param, colors.end, a->obs_point_id); + colors.param, colors.end, a->collector_set_id); + + ds_put_format(fp->s, ",%sobs_domain_id=%s", colors.param, colors.end); + if (a->obs_domain_src.field) { + mf_format_subfield(&a->obs_domain_src, fp->s); + } else { + ds_put_format(fp->s, "%"PRIu32, a->obs_domain_imm); + } + ds_put_format(fp->s, ",%sobs_point_id=%s", colors.param, colors.end); + if (a->obs_point_src.field) { + mf_format_subfield(&a->obs_point_src, fp->s); + } else { + ds_put_format(fp->s, "%"PRIu32, a->obs_point_imm); + } if (a->sampling_port != OFPP_NONE) { ds_put_format(fp->s, ",%ssampling_port=%s", colors.param, colors.end); ofputil_format_port(a->sampling_port, fp->port_map, fp->s); diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 323a58cbf..2aff48f5e 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -5909,6 +5909,44 @@ xlate_fin_timeout(struct xlate_ctx *ctx, } } +static uint32_t +ofpact_sample_get_domain(struct xlate_ctx *ctx, + const struct ofpact_sample *os) +{ + if (os->obs_domain_src.field) { + union mf_subvalue *value = xmalloc(sizeof *value); + uint32_t obs_domain_id; + + memset(value, 0xff, sizeof *value); + obs_domain_id = mf_get_subfield(&os->obs_domain_src, &ctx->xin->flow); + mf_write_subfield_flow(&os->obs_domain_src, value, &ctx->wc->masks); + + free(value); + return obs_domain_id; + } else { + return os->obs_domain_imm; + } +} + +static uint32_t +ofpact_sample_get_point(struct xlate_ctx *ctx, + const struct ofpact_sample *os) +{ + if (os->obs_point_src.field) { + union mf_subvalue *value = xmalloc(sizeof *value); + uint32_t obs_point_id; + + memset(value, 0xff, sizeof *value); + obs_point_id = mf_get_subfield(&os->obs_point_src, &ctx->xin->flow); + mf_write_subfield_flow(&os->obs_point_src, value, &ctx->wc->masks); + + free(value); + return obs_point_id; + } else { + return os->obs_point_imm; + } +} + static void xlate_fill_ipfix_sample(struct xlate_ctx *ctx, const struct ofpact_sample *os, @@ -5975,8 +6013,10 @@ xlate_fill_ipfix_sample(struct xlate_ctx *ctx, userspace->cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid; userspace->cookie.flow_sample.probability = os->probability; userspace->cookie.flow_sample.collector_set_id = os->collector_set_id; - userspace->cookie.flow_sample.obs_domain_id = os->obs_domain_id; - userspace->cookie.flow_sample.obs_point_id = os->obs_point_id; + userspace->cookie.flow_sample.obs_domain_id = + ofpact_sample_get_domain(ctx, os); + userspace->cookie.flow_sample.obs_point_id = + ofpact_sample_get_point(ctx, os); userspace->cookie.flow_sample.output_odp_port = output_odp_port; userspace->cookie.flow_sample.direction = os->direction; userspace->include_actions = false; @@ -5987,7 +6027,8 @@ xlate_sample_action(struct xlate_ctx *ctx, const struct ofpact_sample *os, bool last) { - uint8_t cookie_buf[sizeof(os->obs_domain_id) + sizeof(os->obs_point_id)]; + uint8_t cookie_buf[sizeof(os->obs_domain_imm) + + sizeof(os->obs_point_imm)]; struct dpif_lsample *lsample = ctx->xbridge->lsample; struct dpif_ipfix *ipfix = ctx->xbridge->ipfix; struct compose_sample_args compose_args = {}; @@ -6018,12 +6059,12 @@ xlate_sample_action(struct xlate_ctx *ctx, ofpbuf_use_stub(&psample.cookie, cookie_buf, sizeof cookie_buf); data = ofpbuf_put_uninit(&psample.cookie, - sizeof(os->obs_domain_id)); - *data = htonl(os->obs_domain_id); + sizeof(os->obs_domain_imm)); + *data = htonl(ofpact_sample_get_domain(ctx, os)); data = ofpbuf_put_uninit(&psample.cookie, - sizeof(os->obs_point_id)); - *data = htonl(os->obs_point_id); + sizeof(os->obs_point_imm)); + *data = htonl(ofpact_sample_get_point(ctx, os)); compose_args.psample = &psample; diff --git a/python/ovs/flow/ofp.py b/python/ovs/flow/ofp.py index 3d3226c91..f011b0460 100644 --- a/python/ovs/flow/ofp.py +++ b/python/ovs/flow/ofp.py @@ -30,7 +30,7 @@ from ovs.flow.ofp_act import ( decode_move_field, decode_dec_ttl, decode_chk_pkt_larger, - decode_zone, + decode_field_or_int, decode_learn, ) @@ -330,7 +330,7 @@ class OFPFlow(Flow): KVDecoders( { "commit": decode_flag, - "zone": decode_zone, + "zone": decode_field_or_int, "table": decode_int, "nat": decode_nat, "force": decode_flag, @@ -426,8 +426,8 @@ class OFPFlow(Flow): { "probability": decode_int, "collector_set_id": decode_int, - "obs_domain_id": decode_int, - "obs_point_id": decode_int, + "obs_domain_id": decode_field_or_int, + "obs_point_id": decode_field_or_int, "sampling_port": decode_default, "ingress": decode_flag, "egress": decode_flag, diff --git a/python/ovs/flow/ofp_act.py b/python/ovs/flow/ofp_act.py index 2c85076a3..32c5a8e17 100644 --- a/python/ovs/flow/ofp_act.py +++ b/python/ovs/flow/ofp_act.py @@ -246,8 +246,7 @@ def decode_chk_pkt_larger(value): return {"pkt_len": pkt_len, "dst": dst} -# CT decoders -def decode_zone(value): +def decode_field_or_int(value): """Decodes the value of the 'zone' keyword (part of the ct action).""" try: return int(value, 0) @@ -256,6 +255,7 @@ def decode_zone(value): return decode_field(value) +# CT decoders def decode_learn(action_decoders): """Create the decoder to be used to decode the 'learn' action. diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at index 40a23bb15..fc531bc9f 100644 --- a/tests/ofp-actions.at +++ b/tests/ofp-actions.at @@ -489,6 +489,9 @@ ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000 # actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678) ffff 0018 00002320 001d 3039 00005BA0 00008707 0000B26E +# actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=NXM_NX_CT_LABEL[0..31],obs_point_id=NXM_NX_CT_LABEL[32..63],sampling_port=0) +ffff 0028 00002320 0033 3039 00005ba0 0001d810 001f0000 0001d810 081f0000 0000 000000000000 + # bad OpenFlow11 actions: OFPBAC_BAD_OUT_PORT & ofp_actions|WARN|bad action at offset 0 (OFPBAC_BAD_OUT_PORT): & 00000000 00 00 00 10 ff ff ff ff-00 00 00 00 00 00 00 00 @@ -1121,6 +1124,8 @@ bad_action 'unroll_xlate' "UNROLL is an internal action that shouldn't be used v # sample bad_action 'sample(probability=0)' 'invalid probability value "0"' bad_action 'sample(sampling_port=asdf)' 'asdf: unknown port' +bad_action 'sample(probability=12345,obs_domain_id=NXM_NX_CT_LABEL[[0..30]])' 'invalid length of obs_domain_id field (31). Must be 32' +bad_action 'sample(probability=12345,obs_point_id=NXM_NX_CT_LABEL[[0..32]])' 'invalid length of obs_point_id field (33). Must be 32' bad_action 'sample(foo=bar)' 'invalid key "foo" in "sample" argument' bad_action 'sample' 'non-zero "probability" must be specified on sample' diff --git a/tests/system-traffic.at b/tests/system-traffic.at index ddab4ece3..2ed425029 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -9388,3 +9388,77 @@ dnl OVS will fail to send IPFIX packets because the target is localhost dnl and the port is closed. Ignore the message it generates. OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"]) AT_CLEANUP + +AT_SETUP([psample - from ct label]) +CHECK_CONNTRACK() +OVS_TRAFFIC_VSWITCHD_START() +OVS_CHECK_PSAMPLE() + +ADD_NAMESPACES(at_ns0, at_ns1) +NS_CHECK_EXEC([at_ns0], [sysctl -w net.ipv6.conf.all.disable_ipv6=1], [0], [ignore]) +NS_CHECK_EXEC([at_ns1], [sysctl -w net.ipv6.conf.all.disable_ipv6=1], [0], [ignore]) + +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "e4:11:22:33:44:55") +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "e4:11:22:33:44:66") + +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \ + -- --id=@ipfix create IPFIX targets=\"127.0.0.1:4739\" \ + -- create Flow_Sample_Collector_Set id=1 bridge=@br0 ipfix=@ipfix, local_group_id=10 \ + -- create Flow_Sample_Collector_Set id=2 bridge=@br0 ipfix=@ipfix, local_group_id=12], + [0], [ignore]) + + +m4_define([CT_STORE_ACT], + [ct(zone=5,commit,exec(load:0x0bb102030->NXM_NX_CT_LABEL[[0..31]],load:0xbb405060->NXM_NX_CT_LABEL[[32..63]]))]) + +AT_DATA([flows.txt], [dnl +priority=100,ip actions=ct(zone=5, table=10) +priority=0 actions=NORMAL +table=10,priority=100,ip,ct_state=+trk+new action=SAMPLE_ACTION(1, 2853183536, 2856341600),CT_STORE_ACT,NORMAL +table=10,priority=100,ip,ct_state=+trk-new action=SAMPLE_ACTION(2, NXM_NX_CT_LABEL[[[0..31]]], NXM_NX_CT_LABEL[[[32..63]]]),NORMAL +table=10, priority=50, ip, actions=DROP +]) + +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) + +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample1.pid]) + +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl +1 packets transmitted, 1 received, 0% packet loss, time 0ms +]) + +m4_define([SAMPLE1], [m4_join([ ], + [group_id=0xa], + [obs_domain=0xaa102030,obs_point=0xaa405060], + [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])]) + +m4_define([SAMPLE2], [m4_join([ ], + [group_id=0xc], + [obs_domain=0xbb102030,obs_point=0xbb405060], + [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])]) +AT_CHECK([grep -qE 'SAMPLE1' psample.out]) +AT_CHECK([grep -qE 'SAMPLE2' psample.out]) + +m4_define([FLOW_MATCH], [m4_join([], + [ct_label(0xbb405060bb102030/0xffffffffffffffff).*actions:], + [actions:psample(group=12,cookie=0xbb102030bb405060),], + [userspace(pid=[[0-9]]+,flow_sample(.*obs_domain_id=3138396208,obs_point_id=3141554272.*))] +)]) + +AT_CHECK([ovs-appctl dpctl/dump-flows --names filter=in_port=ovs-p1 dnl + | grep -qE 'FLOW_MATCH' ], [0], []) + +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl +Local sample statistics for bridge "br0": +Collector Set ID: 1: + Group ID : 10 + Total packets: 1 + Total bytes : 98 + +Collector Set ID: 2: + Group ID : 12 + Total packets: 1 + Total bytes : 98 +]) + +AT_CLEANUP