From patchwork Mon Sep 26 17:24:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Moreno X-Patchwork-Id: 1682751 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) 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=GHDikKGr; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MbqQ93DWtz1yq3 for ; Tue, 27 Sep 2022 03:25:05 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 59B6782CB7; Mon, 26 Sep 2022 17:25:03 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 59B6782CB7 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=GHDikKGr X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1RRsn9--JnDJ; Mon, 26 Sep 2022 17:25:02 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 3F88F81AA7; Mon, 26 Sep 2022 17:25:01 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 3F88F81AA7 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1863AC0033; Mon, 26 Sep 2022 17:25:01 +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 76AE7C0033 for ; Mon, 26 Sep 2022 17:24:59 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 3DE4840C40 for ; Mon, 26 Sep 2022 17:24:59 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 3DE4840C40 Authentication-Results: smtp2.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=GHDikKGr X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 45V4YUBi9OpW for ; Mon, 26 Sep 2022 17:24:58 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 1AE2240C0B Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp2.osuosl.org (Postfix) with ESMTPS id 1AE2240C0B for ; Mon, 26 Sep 2022 17:24:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1664213097; 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=5WgpGCeRpHQAPVzPYCgUe7J20eogcKMq37gH3tYaKok=; b=GHDikKGrpRwN3Ky/Yq4gegzH5NRlGSXbJe1q2Qi/fhOyOVbyLSJtzUyKvX8vGeSNza2Aq0 RQynvNKRp/VfCswCPsLEBVbDHwYYsx78tjGfkgfEcqxaOJvDAsOjtwrBdrdvXWWzgHHBPk 74cfqQk3M3FSXe2iuPVgpmkl40TlAec= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-536-kVLtG0bBNISNK3-9bYWoNQ-1; Mon, 26 Sep 2022 13:24:55 -0400 X-MC-Unique: kVLtG0bBNISNK3-9bYWoNQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 7F6F9185A794; Mon, 26 Sep 2022 17:24:55 +0000 (UTC) Received: from amorenoz.users.ipa.redhat.com (unknown [10.39.193.44]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6735240C2064; Mon, 26 Sep 2022 17:24:54 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Mon, 26 Sep 2022 19:24:42 +0200 Message-Id: <20220926172444.1311514-2-amorenoz@redhat.com> In-Reply-To: <20220926172444.1311514-1-amorenoz@redhat.com> References: <20220926172444.1311514-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com Subject: [ovs-dev] [PATCH ovn v2 1/3] actions: add sample action X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" sample ovn action encodes into the OFPACT_SAMPLE ovs action. OVN action allows the following parameters: - obs_domain_id: 8-bit integer that identifies the sampling application. This value will be combined with the datapath's tunnel_id to form the final observation_domain_id that will be used in the OVS action. - obs_point_id: a 32-bit integer or the $cookie macro that will be expanded into the first 32 bits of the lflow's UUID. - probability: a 16-bit integer that specifies the sampling probability. Specifying 0 has no effect and 65535 means sampling all packets. Signed-off-by: Adrian Moreno --- controller/lflow.c | 1 + include/ovn/actions.h | 16 ++++++ lib/actions.c | 120 ++++++++++++++++++++++++++++++++++++++++++ tests/ovn.at | 25 +++++++++ tests/test-ovn.c | 3 ++ utilities/ovn-trace.c | 2 + 6 files changed, 167 insertions(+) diff --git a/controller/lflow.c b/controller/lflow.c index eef44389f..cbda6cdfb 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -1163,6 +1163,7 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, .group_table = l_ctx_out->group_table, .meter_table = l_ctx_out->meter_table, .lflow_uuid = lflow->header_.uuid, + .tunnel_key = ldp->datapath->tunnel_key, .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS, .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE, diff --git a/include/ovn/actions.h b/include/ovn/actions.h index d7ee84dac..c7f40cb7d 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -121,6 +121,7 @@ struct ovn_extend_table; OVNACT(COMMIT_ECMP_NH, ovnact_commit_ecmp_nh) \ OVNACT(CHK_ECMP_NH_MAC, ovnact_result) \ OVNACT(CHK_ECMP_NH, ovnact_result) \ + OVNACT(SAMPLE, ovnact_sample) \ /* enum ovnact_type, with a member OVNACT_ for each action. */ enum OVS_PACKED_ENUM ovnact_type { @@ -456,6 +457,18 @@ struct ovnact_lookup_fdb { struct expr_field dst; /* 1-bit destination field. */ }; +/* OVNACT_SAMPLE */ +struct ovnact_sample { + struct ovnact ovnact; + uint16_t probability; /* probability over UINT16_MAX. */ + uint8_t obs_domain_id; /* most significant byte of the + observation domain id. The other 24 bits + will come from the datapath's tunnel key. */ + uint32_t collector_set_id; /* colector_set_id. */ + uint32_t obs_point_id; /* observation point id. */ + bool use_cookie; /* use cookie as obs_point_id */ +}; + /* OVNACT_COMMIT_ECMP_NH. */ struct ovnact_commit_ecmp_nh { struct ovnact ovnact; @@ -785,6 +798,9 @@ struct ovnact_encode_params { /* The logical flow uuid that drove this action. */ struct uuid lflow_uuid; + /* The tunnel key of the datapath. */ + uint32_t tunnel_key; + /* OVN maps each logical flow table (ltable), one-to-one, onto a physical * OpenFlow flow table (ptable). A number of parameters describe this * mapping and data related to flow tables: diff --git a/lib/actions.c b/lib/actions.c index adbb42db4..95772d9a8 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -4279,6 +4279,124 @@ encode_CHECK_OUT_PORT_SEC(const struct ovnact_result *dl, MLF_CHECK_PORT_SEC_BIT, ofpacts); } +static void +format_SAMPLE(const struct ovnact_sample *sample, struct ds *s) +{ + ds_put_format(s, "sample(probability=%"PRId16, sample->probability); + + ds_put_format(s, ",collector_set=%"PRId32, sample->collector_set_id); + ds_put_format(s, ",obs_domain=%"PRId8, sample->obs_domain_id); + if (sample->use_cookie) { + ds_put_cstr(s, ",obs_point=$cookie"); + } else { + ds_put_format(s, ",obs_point=%"PRId32, sample->obs_point_id); + } + ds_put_format(s, ");"); +} + +static void +encode_SAMPLE(const struct ovnact_sample *sample, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + struct ofpact_sample *os = ofpact_put_SAMPLE(ofpacts); + os->probability = sample->probability; + os->collector_set_id = sample->collector_set_id; + os->obs_domain_id = + (sample->obs_domain_id << 24) | (ep->tunnel_key & 0xFFFFFF); + + if (sample->use_cookie) { + os->obs_point_id = ep->lflow_uuid.parts[0]; + } else { + os->obs_point_id = sample->obs_point_id; + } + os->sampling_port = OFPP_NONE; +} + +static void +parse_sample_arg(struct action_context *ctx, struct ovnact_sample *sample) +{ + if (lexer_match_id(ctx->lexer, "probability")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + if (!action_parse_uint16(ctx, &sample->probability, + "probability")) { + return; + } + } + } else if (lexer_match_id(ctx->lexer, "obs_point")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_MACRO && + !strcmp(ctx->lexer->token.s, "cookie")) { + sample->use_cookie = true; + lexer_get(ctx->lexer); + } else if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + sample->obs_point_id = ntohll(ctx->lexer->token.value.integer); + lexer_get(ctx->lexer); + } else { + lexer_syntax_error(ctx->lexer, + "malformed sample observation_point_id"); + } + } else if (lexer_match_id(ctx->lexer, "obs_domain")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + uint32_t obs_domain = ntohll(ctx->lexer->token.value.integer); + if (obs_domain > UINT8_MAX) { + lexer_syntax_error(ctx->lexer, + "obs_domain must be 8-bit long"); + return; + } + sample->obs_domain_id = obs_domain; + } + lexer_get(ctx->lexer); + } else if (lexer_match_id(ctx->lexer, "collector_set")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + sample->collector_set_id = ntohll(ctx->lexer->token.value.integer); + } + lexer_get(ctx->lexer); + } else { + lexer_syntax_error(ctx->lexer, "unknown argument"); + } +} + +static void +parse_sample(struct action_context *ctx) +{ + struct ovnact_sample * sample = ovnact_put_SAMPLE(ctx->ovnacts); + + if (lexer_match(ctx->lexer, LEX_T_LPAREN)) { + while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) { + parse_sample_arg(ctx, sample); + if (ctx->lexer->error) { + return; + } + lexer_match(ctx->lexer, LEX_T_COMMA); + } + } + if (!sample->probability) { + lexer_error(ctx->lexer, "probability must be greater than zero"); + return; + } +} + +static void +ovnact_sample_free(struct ovnact_sample *sample OVS_UNUSED) +{ +} + static void parse_commit_ecmp_nh(struct action_context *ctx, struct ovnact_commit_ecmp_nh *ecmp_nh) @@ -4790,6 +4908,8 @@ parse_action(struct action_context *ctx) parse_put_fdb(ctx, ovnact_put_PUT_FDB(ctx->ovnacts)); } else if (lexer_match_id(ctx->lexer, "commit_ecmp_nh")) { parse_commit_ecmp_nh(ctx, ovnact_put_COMMIT_ECMP_NH(ctx->ovnacts)); + } else if (lexer_match_id(ctx->lexer, "sample")) { + parse_sample(ctx); } else { lexer_syntax_error(ctx->lexer, "expecting action"); } diff --git a/tests/ovn.at b/tests/ovn.at index 80e9192ca..d54bd5a14 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -2105,6 +2105,31 @@ pop(eth.type); push(abc); Syntax error at `abc' expecting field name. +# sample +sample(probability=100,collector_set=200,obs_domain=0,obs_point=1000); + encodes as sample(probability=100,collector_set_id=200,obs_domain_id=11259375,obs_point_id=1000) + +# sample with obs_domain = 10. Final obs_domain is 0xA << 24 | 0xABCDEF. +sample(probability=100,collector_set=200,obs_domain=10,obs_point=$cookie); + encodes as sample(probability=100,collector_set_id=200,obs_domain_id=179031535,obs_point_id=2863311530) + +sample(probability=10); + formats as sample(probability=10,collector_set=0,obs_domain=0,obs_point=0); + encodes as sample(probability=10,collector_set_id=0,obs_domain_id=11259375,obs_point_id=0) + +sample(probability=0,collector_set=200,obs_domain=0,obs_point=1000); + probability must be greater than zero + +sample(probability=0,collector_set=200,obs_domain=0,obs_point=foo); + Syntax error at `foo' malformed sample observation_point_id. + +sample(probability=0,collector_set=200,obs_domain=300,obs_point=foo); + Syntax error at `300' obs_domain must be 8-bit long. + +sample(probability=10,foo=bar,obs_domain=0,obs_point=1000); + Syntax error at `foo' unknown argument. + + # Miscellaneous negative tests. ; Syntax error at `;'. diff --git a/tests/test-ovn.c b/tests/test-ovn.c index a241f150d..ea319f81e 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -1355,6 +1355,9 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) .common_nat_ct_zone = MFF_LOG_DNAT_ZONE, .in_port_sec_ptable = OFTABLE_CHK_IN_PORT_SEC, .out_port_sec_ptable = OFTABLE_CHK_OUT_PORT_SEC, + .lflow_uuid.parts = + { 0xaaaaaaaa, 0xbbbbbbbb, 0xcccccccc, 0xdddddddd}, + .tunnel_key = 0xabcdef, }; struct ofpbuf ofpacts; ofpbuf_init(&ofpacts, 0); diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index d9e7129d9..fbe548605 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -3298,6 +3298,8 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, break; case OVNACT_CHK_ECMP_NH: break; + case OVNACT_SAMPLE: + break; } } ofpbuf_uninit(&stack);