From patchwork Wed Jun 5 20:23:29 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: 1944152 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=P7L/VoDn; 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 4Vvf7S4rczz20Q5 for ; Thu, 6 Jun 2024 06:24:04 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id EF566611A9; Wed, 5 Jun 2024 20:24:02 +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 uRd2QqrcJMTX; Wed, 5 Jun 2024 20:24:01 +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 smtp3.osuosl.org 8276F611A1 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=P7L/VoDn Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id 8276F611A1; Wed, 5 Jun 2024 20:24:01 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 631E4C0DCE; Wed, 5 Jun 2024 20:24:01 +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 363CAC0DD6 for ; Wed, 5 Jun 2024 20:24:00 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 5C85B812B1 for ; Wed, 5 Jun 2024 20:23:59 +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 uhaCterh632g for ; Wed, 5 Jun 2024 20:23:58 +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 0181E812EC 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 0181E812EC 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=P7L/VoDn 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 0181E812EC for ; Wed, 5 Jun 2024 20:23:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1717619036; 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=Wu47vOG40noNCJsrUwLBt/aWGxH7OjOeLW2OuLMOq4E=; b=P7L/VoDnI62wLDXqMaZWBCQevDweXQ9gb0EdPVzNru3uMFiIyyZnqwYiMqE4eWvS5U2OCl 6TKn5YV5tfo2tKiayDU9E/3ELDQVltV2R+piL6SFfC2/hlu52UlAtUYUvM2VStJg2Ja5+f aVTLgpGJaBqNE1cwsXmi7Y/3IF/supA= 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-312-FoaB_SkNNu6szpOGIbfj8g-1; Wed, 05 Jun 2024 16:23:50 -0400 X-MC-Unique: FoaB_SkNNu6szpOGIbfj8g-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 19A5E195E930; Wed, 5 Jun 2024 20:23:49 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.193.112]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0FFB01956086; Wed, 5 Jun 2024 20:23:46 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Wed, 5 Jun 2024 22:23:29 +0200 Message-ID: <20240605202337.2904041-2-amorenoz@redhat.com> In-Reply-To: <20240605202337.2904041-1-amorenoz@redhat.com> References: <20240605202337.2904041-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [RFC v2 1/9] odp-util: Add support OVS_ACTION_ATTR_EMIT_SAMPLE. 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" 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_EMIT_SAMPLE. The reason is that the sampling rate form the parent "sample" is made available to the nested "emit_sample" by the kernel. Signed-off-by: Adrian Moreno --- include/linux/openvswitch.h | 25 +++++++++ lib/dpif-netdev.c | 1 + lib/dpif.c | 1 + lib/odp-execute.c | 25 ++++++++- lib/odp-util.c | 103 +++++++++++++++++++++++++++++++++++ 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, 183 insertions(+), 1 deletion(-) diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h index d9fb991ef..b4e0647bd 100644 --- a/include/linux/openvswitch.h +++ b/include/linux/openvswitch.h @@ -992,6 +992,30 @@ struct check_pkt_len_arg { }; #endif +#define OVS_EMIT_SAMPLE_COOKIE_MAX_SIZE 16 +/** + * enum ovs_emit_sample_attr - Attributes for %OVS_ACTION_ATTR_EMIT_SAMPLE + * action. + * + * @OVS_EMIT_SAMPLE_ATTR_GROUP: 32-bit number to identify the source of the + * sample. + * @OVS_EMIT_SAMPLE_ATTR_COOKIE: A variable-length binary cookie that contains + * user-defined metadata. The maximum length is 16 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 to limit the size of the packet being emitted. + */ +enum ovs_emit_sample_attr { + OVS_EMIT_SAMPLE_ATTR_UNPSEC, + OVS_EMIT_SAMPLE_ATTR_GROUP, /* u32 number. */ + OVS_EMIT_SAMPLE_ATTR_COOKIE, /* Optional, user specified cookie. */ + __OVS_EMIT_SAMPLE_ATTR_MAX +}; + +#define OVS_EMIT_SAMPLE_ATTR_MAX (__OVS_EMIT_SAMPLE_ATTR_MAX - 1) + + /** * enum ovs_action_attr - Action types. * @@ -1087,6 +1111,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_EMIT_SAMPLE, /* Nested OVS_EMIT_SAMPLE_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..c1171890c 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_EMIT_SAMPLE: case __OVS_ACTION_ATTR_MAX: OVS_NOT_REACHED(); } diff --git a/lib/dpif.c b/lib/dpif.c index 23eb18495..489d6a095 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_EMIT_SAMPLE: 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..967abfd0a 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_EMIT_SAMPLE: 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 "emit_sample" actions rely on the datapath executing the + * parent "sample", storing the probability and making it available + * when the nested "emit_sample" 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_EMIT_SAMPLE) { + 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_EMIT_SAMPLE: 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..02452083f 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_EMIT_SAMPLE: return ATTR_LEN_VARIABLE; case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: @@ -1150,6 +1151,36 @@ format_dec_ttl_action(struct ds *ds, const struct nlattr *attr, ds_put_format(ds, "))"); } +static void +format_odp_emit_sample_action(struct ds *ds, const struct nlattr *attr) +{ + const struct nlattr *a; + unsigned int left; + + ds_put_cstr(ds, "emit_sample("); + + NL_ATTR_FOR_EACH (a, left, + nl_attr_get(attr), nl_attr_get_size(attr)) { + switch (a->nla_type) { + case OVS_EMIT_SAMPLE_ATTR_GROUP: + ds_put_format(ds, "group=%"PRIu32",", nl_attr_get_u32(a)); + break; + case OVS_EMIT_SAMPLE_ATTR_COOKIE: { + const uint8_t *cookie = nl_attr_get(a); + int i; + + ds_put_cstr(ds, "cookie="); + for (i = 0; i < nl_attr_get_size(a); i++) { + ds_put_format(ds, "%02x", cookie[i]); + } + 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 +1340,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_EMIT_SAMPLE: + format_odp_emit_sample_action(ds, a); + break; case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: default: @@ -2358,6 +2392,50 @@ out: return ret; } +static int +parse_odp_emit_sample_action(const char *s, struct ofpbuf *actions) +{ + uint8_t cookie[OVS_EMIT_SAMPLE_COOKIE_MAX_SIZE]; + char buf[2 * OVS_EMIT_SAMPLE_COOKIE_MAX_SIZE + 1]; + bool has_group = false; + size_t cookie_len = 0; + uint32_t group; + int n = 0; + + if (!ovs_scan_len(s, &n, "emit_sample(")) { + 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=%32[0-9a-fA-F]", buf) && n > 7) { + struct ofpbuf b; + + ofpbuf_use_stub(&b, cookie, OVS_EMIT_SAMPLE_COOKIE_MAX_SIZE); + ofpbuf_put_hex(&b, buf, &cookie_len); + ofpbuf_uninit(&b); + continue; + } + return -EINVAL; + } + n++; + + if (!has_group) { + return -EINVAL; + } + + odp_put_emit_sample_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 +2797,12 @@ parse_odp_action__(struct parse_odp_context *context, const char *s, } } + { + if (!strncmp(s, "emit_sample(", 12)) { + return parse_odp_emit_sample_action(s, actions); + } + } + { struct ovs_action_push_tnl data; int n; @@ -7828,6 +7912,25 @@ 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_emit_sample_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_EMIT_SAMPLE); + + nl_msg_put_u32(odp_actions, OVS_EMIT_SAMPLE_ATTR_GROUP, group_id); + if (cookie && cookie_len) { + ovs_assert(cookie_len <= OVS_EMIT_SAMPLE_COOKIE_MAX_SIZE); + nl_msg_put_unspec(odp_actions, OVS_EMIT_SAMPLE_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..2159f0897 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_emit_sample_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..15e92ba74 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_EMIT_SAMPLE: case __OVS_ACTION_ATTR_MAX: default: break; diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index 4a68e9b94..9db499fd4 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_EMIT_SAMPLE: case __OVS_ACTION_ATTR_MAX: default: break; diff --git a/python/ovs/flow/odp.py b/python/ovs/flow/odp.py index 7d9b165d4..896ae34bd 100644 --- a/python/ovs/flow/odp.py +++ b/python/ovs/flow/odp.py @@ -343,6 +343,14 @@ class ODPFlow(Flow): } ) ), + "emit_sample": 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..e5c2ee07c 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) +emit_sample(group=12,cookie=01020304050607080910111213141516) +emit_sample(group=12) +sample(sample=50.0%,actions(emit_sample(group=12,cookie=01020304))) +sample(sample=50.0%,actions(userspace(pid=42,userdata(0102030400000000)),emit_sample(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)) +emit_sample(group_id=12,cookie=0102030405060708090a0b0c0d0e0f0f0f) +emit_sample(cookie=010203) +emit_sample(group=12,cookie=010203,group=12) +emit_sample(group=abc) +emit_sample(group=12,cookie=wrong) +emit_sample() ]) 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 Wed Jun 5 20:23:30 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: 1944151 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=N1SDK2ni; 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 4Vvf7Q5ntgz20Q5 for ; Thu, 6 Jun 2024 06:24:02 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 3B06D42391; Wed, 5 Jun 2024 20:24:01 +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 fbGtwCvMbDWQ; Wed, 5 Jun 2024 20:23:59 +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 AC9EE419D0 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=N1SDK2ni Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id AC9EE419D0; Wed, 5 Jun 2024 20:23:59 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 76E8EC0DCE; Wed, 5 Jun 2024 20:23:59 +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 1CE98C0037 for ; Wed, 5 Jun 2024 20:23:58 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 0BC3F81307 for ; Wed, 5 Jun 2024 20:23:58 +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 eyCiQotmQrKo for ; Wed, 5 Jun 2024 20:23:57 +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 12929812B1 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 12929812B1 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=N1SDK2ni 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 12929812B1 for ; Wed, 5 Jun 2024 20:23:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1717619036; 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=SAvFD9cXu7cxufsQgmQiuYFNxRaTUQDhPp+L+tvcIIo=; b=N1SDK2niacUruKVtb1dDH3D3T8SYd1s1wLWfD0OWyMG3/oHBm8nbTBi8RiyrVcOxaRvLAV EQW4YbaUMIB7J+1yAlNxh6S4/hK4tJ+0W2xa9MxC6BRlJiSQEsh/uCyqIzkl8djVu2pt+O mcPrDk8uXPrlczhf/WXrjaxDV2HfyLc= 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-594-XIRfaOHSOqyVubbiOUEzmw-1; Wed, 05 Jun 2024 16:23:52 -0400 X-MC-Unique: XIRfaOHSOqyVubbiOUEzmw-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 AEB121954B2E; Wed, 5 Jun 2024 20:23:51 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.193.112]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7CB8F1956086; Wed, 5 Jun 2024 20:23:49 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Wed, 5 Jun 2024 22:23:30 +0200 Message-ID: <20240605202337.2904041-3-amorenoz@redhat.com> In-Reply-To: <20240605202337.2904041-1-amorenoz@redhat.com> References: <20240605202337.2904041-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [RFC v2 2/9] ofproto_dpif: Check for emit_sample support. 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" Only kernel datapath supports this action so add a function in dpif.c that checks for that. Signed-off-by: Adrian Moreno Acked-by: Eelco Chaudron --- lib/dpif.c | 7 +++++++ lib/dpif.h | 1 + ofproto/ofproto-dpif.c | 45 ++++++++++++++++++++++++++++++++++++++++++ ofproto/ofproto-dpif.h | 6 +++++- 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/lib/dpif.c b/lib/dpif.c index 489d6a095..ecba967c3 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_emit_sample(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..08473ea6f 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -942,6 +942,7 @@ 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_synced_dp_layers(struct dpif *); +bool dpif_may_support_emit_sample(const struct dpif *); /* Log functions. */ struct vlog_module; diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 32d037be6..035479285 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_emit_sample_supported(struct ofproto_dpif *ofproto) +{ + return ofproto->backer->rt_support.emit_sample; +} + /* 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,44 @@ check_add_mpls(struct dpif_backer *backer) return supported; } +/* Tests whether 'backer''s datapath supports the OVS_ACTION_ATTR_EMIT_SAMPLE + * action. */ +static bool +check_emit_sample(struct dpif_backer *backer) +{ + uint8_t cookie[OVS_EMIT_SAMPLE_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_emit_sample_action(&actions, 10, cookie, sizeof cookie); + + supported = dpif_may_support_emit_sample(backer->dpif) && + dpif_probe_feature(backer->dpif, "emit_sample", &key, &actions, NULL); + + ofpbuf_uninit(&actions); + VLOG_INFO("%s: Datapath %s emit_sample", + 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 +1742,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.emit_sample = check_emit_sample(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..ae6568463 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 emit_sample action. */ \ + DPIF_SUPPORT_FIELD(bool, emit_sample, "emit_sample") /* Stores the various features which the corresponding backer supports. */ @@ -411,5 +414,6 @@ bool ofproto_dpif_ct_zone_timeout_policy_get_name( uint8_t nw_proto, char **tp_name, bool *unwildcard); bool ovs_explicit_drop_action_supported(struct ofproto_dpif *); +bool ovs_emit_sample_supported(struct ofproto_dpif *); #endif /* ofproto-dpif.h */ From patchwork Wed Jun 5 20:23:31 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: 1944153 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=hngUyovL; 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 4Vvf7W71MLz20Q5 for ; Thu, 6 Jun 2024 06:24:07 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 4CC47611D5; Wed, 5 Jun 2024 20:24:06 +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 OZq3DzZQna3f; Wed, 5 Jun 2024 20:24:05 +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 smtp3.osuosl.org D9FD2611C5 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=hngUyovL Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id D9FD2611C5; Wed, 5 Jun 2024 20:24:04 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BEC14C0077; Wed, 5 Jun 2024 20:24:04 +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 23EF6C0DD2 for ; Wed, 5 Jun 2024 20:24:03 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 8D54081AEA for ; Wed, 5 Jun 2024 20:24:01 +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 QML6thIwmjUI for ; Wed, 5 Jun 2024 20:24:00 +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 BBDEF8137D 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 BBDEF8137D 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=hngUyovL 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 BBDEF8137D for ; Wed, 5 Jun 2024 20:23:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1717619038; 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=9Chl3LfmBk/HoIpuozcq9a3DeuOzDfnItTR3mr2StHk=; b=hngUyovLXAP6sPdwXDOYCe4VEiHvwDcoa7V8XHjZNyryHuCEkkfMt9nVO7vRsNWSBrqE0k zsr4OfoyFsSDxzWmW/11/gYgcYm+yUDQIEsvXuZ4qV0kbSMel50zLyngRqP+Mt/GmxD0/h C8pJAS9+dERW8n0cTlXfgfejcqt1jpQ= 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-626-mMR0d1D2PeimDyDQqzXcQQ-1; Wed, 05 Jun 2024 16:23:55 -0400 X-MC-Unique: mMR0d1D2PeimDyDQqzXcQQ-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 C275A1954219; Wed, 5 Jun 2024 20:23:54 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.193.112]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 130CD1956086; Wed, 5 Jun 2024 20:23:51 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Wed, 5 Jun 2024 22:23:31 +0200 Message-ID: <20240605202337.2904041-4-amorenoz@redhat.com> In-Reply-To: <20240605202337.2904041-1-amorenoz@redhat.com> References: <20240605202337.2904041-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [RFC v2 3/9] ofproto: Add ofproto-dpif-lsample. 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" 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 | 185 +++++++++++++++++++++++++++++++++ ofproto/ofproto-dpif-lsample.h | 34 ++++++ ofproto/ofproto-dpif.c | 37 +++++++ ofproto/ofproto-dpif.h | 1 + ofproto/ofproto-provider.h | 9 ++ ofproto/ofproto.c | 12 +++ ofproto/ofproto.h | 8 ++ 8 files changed, 288 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..fd39bf561 100644 --- a/ofproto/automake.mk +++ b/ofproto/automake.mk @@ -34,6 +34,8 @@ ofproto_libofproto_la_SOURCES = \ ofproto/ofproto-dpif-mirror.h \ ofproto/ofproto-dpif-monitor.c \ ofproto/ofproto-dpif-monitor.h \ + ofproto/ofproto-dpif-lsample.c \ + ofproto/ofproto-dpif-lsample.h \ ofproto/ofproto-dpif-rid.c \ ofproto/ofproto-dpif-rid.h \ ofproto/ofproto-dpif-sflow.c \ diff --git a/ofproto/ofproto-dpif-lsample.c b/ofproto/ofproto-dpif-lsample.c new file mode 100644 index 000000000..7bdafac19 --- /dev/null +++ b/ofproto/ofproto-dpif-lsample.c @@ -0,0 +1,185 @@ +/* + * 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) +{ + struct lsample_exporter_node *node; + const struct ofproto_lsample_options *opt; + 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) { + free(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..c23ea8372 --- /dev/null +++ b/ofproto/ofproto-dpif-lsample.h @@ -0,0 +1,34 @@ +/* + * 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 035479285..067f60df3 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" @@ -2515,6 +2516,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.emit_sample) { + 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) { @@ -7085,6 +7121,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 ae6568463..55a15b2a3 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 Wed Jun 5 20:23:32 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: 1944154 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=N6fuENIr; dkim-atps=neutral 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=patchwork.ozlabs.org) 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 (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Vvf7j2fXSz20Q5 for ; Thu, 6 Jun 2024 06:24:17 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id D55B184907; Wed, 5 Jun 2024 20:24:14 +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 1kEYPBBSZSHL; Wed, 5 Jun 2024 20:24:11 +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 369BE8450B 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=N6fuENIr Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTPS id 369BE8450B; Wed, 5 Jun 2024 20:24:07 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BA28BC0077; Wed, 5 Jun 2024 20:24:07 +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 3A6D3C0077 for ; Wed, 5 Jun 2024 20:24:07 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id E8F7181A47 for ; Wed, 5 Jun 2024 20:24:04 +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 oCaUrnNwoAfS for ; Wed, 5 Jun 2024 20:24:02 +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 77D0881E1D 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 77D0881E1D 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 77D0881E1D for ; Wed, 5 Jun 2024 20:24:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1717619041; 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=HSsxZv3TdqASB9pahM3m+qEVgYk3dBwc+qBoQ4xLmn4=; b=N6fuENIrkGGTXQQI0gt8+UJRle1aCttsuhPLc5LfGu5Ia5uIyV/ojx961xg9DnjlNg7aik 7m+d7nKsbaqm0PmY1JTXZ8uGtmTsXtAd3MCZIS0BvlZzEnAqqbMa7+S1ukPQvacrNeSuxi hTq+EplBxchHe/Mbpx89JEPRCv8LYx4= 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-692-eh28VHigOEeAh0JzIbdyvw-1; Wed, 05 Jun 2024 16:23:58 -0400 X-MC-Unique: eh28VHigOEeAh0JzIbdyvw-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 5AACC1954232; Wed, 5 Jun 2024 20:23:57 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.193.112]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1A6011956086; Wed, 5 Jun 2024 20:23:54 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Wed, 5 Jun 2024 22:23:32 +0200 Message-ID: <20240605202337.2904041-5-amorenoz@redhat.com> In-Reply-To: <20240605202337.2904041-1-amorenoz@redhat.com> References: <20240605202337.2904041-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [RFC v2 4/9] vswitchd: Add local sampling to vswitchd schema. 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" Add as new column in the Flow_Sample_Collector_Set table named "local_sample_group" which enables this feature. Signed-off-by: Adrian Moreno --- NEWS | 4 ++ vswitchd/bridge.c | 78 +++++++++++++++++++++++++++++++++++--- vswitchd/vswitch.ovsschema | 9 ++++- vswitchd/vswitch.xml | 39 +++++++++++++++++-- 4 files changed, 119 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index b92cec532..1c05a7120 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,10 @@ Post-v3.3.0 - The primary development branch has been renamed from 'master' to 'main'. The OVS tree remains hosted on GitHub. https://github.com/openvswitch/ovs.git + - 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 via the new datapath action called "emit_sample". + Linux kernel datapath is the first to support this feature. v3.3.0 - 16 Feb 2024 diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 95a65fcdc..cd7dc6646 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 constains 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 valid local + * sampling configuraiton. */ +static bool +ovsrec_fscs_is_valid_local(const struct ovsrec_flow_sample_collector_set *fscs, + const struct bridge *br) +{ + return fscs->local_sample_group && fscs->n_local_sample_group == 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_sample_group; + 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..f945451cd 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": "3864090052 27769", "tables": { "Open_vSwitch": { "columns": { @@ -562,6 +562,11 @@ "type": {"key": {"type": "uuid", "refTable": "IPFIX"}, "min": 0, "max": 1}}, + "local_sample_group": { + "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 8a1b607d7..2a5223203 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_sample_group 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_sample_group 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. + + 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_sample_group and ipfix can be + configured simultaneously.

@@ -7030,6 +7057,10 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \ record per sampled packet to. + + Configuration of the sample group 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 Wed Jun 5 20:23:33 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: 1944155 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=VvobKUhh; 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 4Vvf7l5Gdhz20Q5 for ; Thu, 6 Jun 2024 06:24:19 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id D35C6613D9; Wed, 5 Jun 2024 20:24:17 +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 s7s-1sazqfDV; Wed, 5 Jun 2024 20:24:13 +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 smtp3.osuosl.org 5A0A161230 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=VvobKUhh Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id 5A0A161230; Wed, 5 Jun 2024 20:24:13 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 06F9AC0077; Wed, 5 Jun 2024 20:24:13 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 4C60CC0077 for ; Wed, 5 Jun 2024 20:24:12 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 5DCD5416B6 for ; Wed, 5 Jun 2024 20:24:07 +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 KT-KyMUpdWqY for ; Wed, 5 Jun 2024 20:24:05 +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 smtp2.osuosl.org 3D73B41657 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 3D73B41657 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=VvobKUhh 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 3D73B41657 for ; Wed, 5 Jun 2024 20:24:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1717619044; 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=FpAUEkdwa00fWAWTgMeO77yvOky9uweKLMElFxuZ8Fg=; b=VvobKUhhFdWdeZvdATcipLA+EoVwZUj6E6on6rLZpV06vwfWGrxo6pjSaL86SdZBodH/zF KAIlev2efLxSVTTmn1qQYbmm6Q8EwC7XV8alya+FAOYZoxFLhF9fZko2qfhBrzru1OWc3H eWCGqHDB8II4f75BE7EFmY/3x0JZGtg= 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-306-4nqq5n0_OYWZHjTYauxpBw-1; Wed, 05 Jun 2024 16:24:01 -0400 X-MC-Unique: 4nqq5n0_OYWZHjTYauxpBw-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 1BCA51954B02; Wed, 5 Jun 2024 20:24:00 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.193.112]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 89CBE1956086; Wed, 5 Jun 2024 20:23:57 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Wed, 5 Jun 2024 22:23:33 +0200 Message-ID: <20240605202337.2904041-6-amorenoz@redhat.com> In-Reply-To: <20240605202337.2904041-1-amorenoz@redhat.com> References: <20240605202337.2904041-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [RFC v2 5/9] ofproto-dpif-xlate: Use emit_sample for local sample. 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" Use the newly added emit_sample to implement OpenFlow sample() actions with local sampling configuration. Signed-off-by: Adrian Moreno --- ofproto/ofproto-dpif-lsample.c | 17 ++++ ofproto/ofproto-dpif-lsample.h | 6 ++ ofproto/ofproto-dpif-xlate.c | 163 ++++++++++++++++++++++++--------- ofproto/ofproto-dpif-xlate.h | 3 +- ofproto/ofproto-dpif.c | 2 +- 5 files changed, 144 insertions(+), 47 deletions(-) diff --git a/ofproto/ofproto-dpif-lsample.c b/ofproto/ofproto-dpif-lsample.c index 7bdafac19..2c0b5da89 100644 --- a/ofproto/ofproto-dpif-lsample.c +++ b/ofproto/ofproto-dpif-lsample.c @@ -139,6 +139,23 @@ dpif_lsample_set_options(struct dpif_lsample *lsample, return changed; } +/* Returns the group_id of the exporter with the 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 c23ea8372..f13425575 100644 --- a/ofproto/ofproto-dpif-lsample.h +++ b/ofproto/ofproto-dpif-lsample.h @@ -19,6 +19,7 @@ #include #include +#include struct dpif_lsample; struct ofproto_lsample_options; @@ -31,4 +32,9 @@ 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..5bd215d31 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. */ @@ -687,6 +689,7 @@ static void xlate_xbridge_set(struct xbridge *, struct dpif *, const struct dpif_sflow *, const struct dpif_ipfix *, const struct netflow *, + const struct dpif_lsample *, bool forward_bpdu, bool has_in_band, const struct dpif_backer_support *, const struct xbridge_addr *); @@ -1070,6 +1073,7 @@ xlate_xbridge_set(struct xbridge *xbridge, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, const struct netflow *netflow, + const struct dpif_lsample *lsample, bool forward_bpdu, bool has_in_band, const struct dpif_backer_support *support, const struct xbridge_addr *addr) @@ -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); @@ -1214,8 +1223,9 @@ xlate_xbridge_copy(struct xbridge *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->lsample, 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); } @@ -1373,6 +1383,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, const struct netflow *netflow, + const struct dpif_lsample *lsample, 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, + netflow, lsample, 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,6 +3369,11 @@ xlate_normal(struct xlate_ctx *ctx) } } +struct emit_sample_args { + uint32_t group_id; + struct ofpbuf cookie; +}; + /* 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. @@ -3370,7 +3387,8 @@ xlate_normal(struct xlate_ctx *ctx) static size_t compose_sample_action(struct xlate_ctx *ctx, const uint32_t probability, - const struct user_action_cookie *cookie, + const struct user_action_cookie *upcall, + const struct emit_sample_args *emit, const odp_port_t tunnel_out_port, bool include_actions) { @@ -3379,14 +3397,20 @@ compose_sample_action(struct xlate_ctx *ctx, return 0; } + /* At least one of upcall or emit_sample config must be provided. */ + ovs_assert(upcall || emit); + /* 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; /* When meter action is not required, avoid generate sample action * for 100% sampling rate. */ - bool is_sample = probability < UINT32_MAX || meter_id != UINT32_MAX; + bool is_sample = (probability < UINT32_MAX || + (upcall && meter_id != UINT32_MAX)); + size_t sample_offset = 0, actions_offset = 0; if (is_sample) { sample_offset = nl_msg_start_nested(ctx->odp_actions, @@ -3397,19 +3421,26 @@ compose_sample_action(struct xlate_ctx *ctx, OVS_SAMPLE_ATTR_ACTIONS); } - if (meter_id != UINT32_MAX) { - nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_METER, meter_id); + if (emit) { + odp_put_emit_sample_action(ctx->odp_actions, emit->group_id, + emit->cookie.data, emit->cookie.size); } - 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) { + if (upcall) { + 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, upcall, sizeof *upcall, + tunnel_out_port, include_actions, + ctx->odp_actions, &cookie_offset); + ovs_assert(res == 0); + } + + if (actions_offset) { nl_msg_end_nested(ctx->odp_actions, actions_offset); nl_msg_end_nested(ctx->odp_actions, sample_offset); } @@ -3440,7 +3471,7 @@ compose_sflow_action(struct xlate_ctx *ctx) cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid; return compose_sample_action(ctx, dpif_sflow_get_probability(sflow), - &cookie, ODPP_NONE, true); + &cookie, NULL, ODPP_NONE, true); } /* If flow IPFIX is enabled, make sure IPFIX flow sample action @@ -3490,7 +3521,7 @@ compose_ipfix_action(struct xlate_ctx *ctx, odp_port_t output_odp_port) compose_sample_action(ctx, dpif_ipfix_get_bridge_exporter_probability(ipfix), - &cookie, tunnel_out_port, false); + &cookie, NULL, tunnel_out_port, false); } /* Fix "sample" action according to data collected while composing ODP actions, @@ -5847,23 +5878,15 @@ 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 user_action_cookie *cookie, + odp_port_t *tunnel_out_port) { 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; - /* If ofp_port in flow sample action is equel to ofp_port, * this sample action is a input port action. */ if (os->sampling_port != OFPP_NONE && @@ -5879,7 +5902,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; + *tunnel_out_port = output_odp_port; emit_set_tunnel = true; } } @@ -5913,20 +5936,70 @@ xlate_sample_action(struct xlate_ctx *ctx, } } - struct user_action_cookie 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; +} - 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 emit_sample_args emit_sample_args; + struct user_action_cookie upcall_cookie; + odp_port_t tunnel_out_port = ODPP_NONE; + bool emit_sample = false; + uint32_t group_id; + + if (!ipfix && !lsample) { + 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; + + if (ipfix) { + xlate_fill_ipfix_sample(ctx, os, ipfix, &upcall_cookie, + &tunnel_out_port); + } + if (lsample) { + if (dpif_lsample_get_group_id(lsample, + os->collector_set_id, + &group_id)) { + emit_sample = true; + ofpbuf_use_stub(&emit_sample_args.cookie, cookie_buf, + sizeof cookie_buf); + + emit_sample_args.group_id = group_id; + ofpbuf_put(&emit_sample_args.cookie, &os->obs_domain_id, + sizeof(os->obs_domain_id)); + ofpbuf_put(&emit_sample_args.cookie, &os->obs_point_id, + sizeof(os->obs_point_id)); + } + } + + if (!ipfix && !emit_sample) { + return; + } + + compose_sample_action(ctx, probability, ipfix ? &upcall_cookie : NULL, + emit_sample ? &emit_sample_args : NULL, + tunnel_out_port, false); + + if (emit_sample) { + ofpbuf_uninit(&emit_sample_args.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..164ff3713 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -177,7 +177,8 @@ void xlate_ofproto_set(struct ofproto_dpif *, const char *name, struct dpif *, 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_lsample *, 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 067f60df3..48167751f 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->netflow, ofproto->lsample, ofproto->up.forward_bpdu, connmgr_has_in_band(ofproto->up.connmgr), &ofproto->backer->rt_support); From patchwork Wed Jun 5 20:23:34 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: 1944156 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=NKoG37dH; 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 4Vvf7m5rN4z20Wh for ; Thu, 6 Jun 2024 06:24:20 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id A04CA41761; Wed, 5 Jun 2024 20:24:18 +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 Op-7DpvfFt3F; Wed, 5 Jun 2024 20:24:16 +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 DCC9D4165E 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=NKoG37dH Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id DCC9D4165E; Wed, 5 Jun 2024 20:24:15 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 75AE6C0DD8; Wed, 5 Jun 2024 20:24:15 +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 1EA11C0DD6 for ; Wed, 5 Jun 2024 20:24:14 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 12BE6423D9 for ; Wed, 5 Jun 2024 20:24:09 +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 gbMBctI6QDIG for ; Wed, 5 Jun 2024 20:24:08 +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 DAC4F423BE 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 DAC4F423BE 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=NKoG37dH 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 DAC4F423BE for ; Wed, 5 Jun 2024 20:24:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1717619046; 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=Z6IWqHqpPLF8+InoAK/z+qX9xGH+up4ml9Ge5jDmy/8=; b=NKoG37dHYZUqjQlNKRoQFJUzHTNM3zZ6qXKVjCOfM/e7UcrWWwAS49BhdkWN0j7SV7PMCU aM2zKAlcmb2RO7Vne8cjSIRA5gMW4RA7ICFcKOWewxtv7V74LfuzYVTyPqOR44Sa0S8yae uOelzU38UmD+pAN7+r5tTkjC0c2uBx0= 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-215-KSrJHz_-ObaQ-PIDFXcL-g-1; Wed, 05 Jun 2024 16:24:03 -0400 X-MC-Unique: KSrJHz_-ObaQ-PIDFXcL-g-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 A56701955BE1; Wed, 5 Jun 2024 20:24:02 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.193.112]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4DCF01956086; Wed, 5 Jun 2024 20:24:00 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Wed, 5 Jun 2024 22:23:34 +0200 Message-ID: <20240605202337.2904041-7-amorenoz@redhat.com> In-Reply-To: <20240605202337.2904041-1-amorenoz@redhat.com> References: <20240605202337.2904041-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [RFC v2 6/9] ofproto-dpif-xlate-cache: Add lsample to xcache. 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" 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 | 15 +++++++++++++++ ofproto/ofproto-dpif.c | 1 + 6 files changed, 54 insertions(+), 1 deletion(-) diff --git a/ofproto/ofproto-dpif-lsample.c b/ofproto/ofproto-dpif-lsample.c index 2c0b5da89..0c71e354d 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 f13425575..2ce096161 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); void dpif_lsample_unref(struct dpif_lsample *); @@ -36,5 +37,8 @@ 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..508e5fcb2 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-mirror.h" +#include "ofproto/ofproto-dpif-lsample.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 5bd215d31..d7648e02c 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -5986,6 +5986,21 @@ xlate_sample_action(struct xlate_ctx *ctx, sizeof(os->obs_domain_id)); ofpbuf_put(&emit_sample_args.cookie, &os->obs_point_id, sizeof(os->obs_point_id)); + + + 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; + } + } } diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 48167751f..e5a7f0fa5 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -5157,6 +5157,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 Wed Jun 5 20:23:35 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: 1944157 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=S9t31575; 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 4Vvf7z0pgYz20Q5 for ; Thu, 6 Jun 2024 06:24:31 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 4631E611DF; Wed, 5 Jun 2024 20:24:29 +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 C8VHJGR7XHw8; Wed, 5 Jun 2024 20:24: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 smtp3.osuosl.org 424B1613E6 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=S9t31575 Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id 424B1613E6; Wed, 5 Jun 2024 20:24:22 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id EDC4EC0077; Wed, 5 Jun 2024 20:24:21 +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 106D6C0037 for ; Wed, 5 Jun 2024 20:24:21 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 6441F423E8 for ; Wed, 5 Jun 2024 20:24:10 +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 Xr4Vgque8-UH for ; Wed, 5 Jun 2024 20:24: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 smtp4.osuosl.org 36321423E3 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 36321423E3 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=S9t31575 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 36321423E3 for ; Wed, 5 Jun 2024 20:24:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1717619047; 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=KklHd56cWcEBCMgNNmTEscX783cg1UQ5BUGdrdY2O6c=; b=S9t31575pkoa3X14wMRHsP2kMWI+rVxD2nbE6I/zSj7gtF62XRDVabi7/MQnAf/AGxC9oX vNQenIfxf4UGlJe0pVMxWOuX384T29RcXhALH3MasrQ9hgjCX4YG9Oo4miVNVHjmH1EGV6 sl91rXjuaSN1te9bKD3VY0j7eWMY97A= 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-655-DewuFj-qNRWfC8bl8IcLYw-1; Wed, 05 Jun 2024 16:24:06 -0400 X-MC-Unique: DewuFj-qNRWfC8bl8IcLYw-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 37484195E91E; Wed, 5 Jun 2024 20:24:05 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.193.112]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D7DD71956086; Wed, 5 Jun 2024 20:24:02 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Wed, 5 Jun 2024 22:23:35 +0200 Message-ID: <20240605202337.2904041-8-amorenoz@redhat.com> In-Reply-To: <20240605202337.2904041-1-amorenoz@redhat.com> References: <20240605202337.2904041-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [RFC v2 7/9] ofproto-dpif-lsample: Show stats via unixctl. 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" Add a command to dump statistics per exporter. Signed-off-by: Adrian Moreno --- NEWS | 2 + ofproto/ofproto-dpif-lsample.c | 113 +++++++++++++++++++++++++++++++++ ofproto/ofproto-dpif-lsample.h | 1 + ofproto/ofproto-dpif.c | 1 + 4 files changed, 117 insertions(+) diff --git a/NEWS b/NEWS index 1c05a7120..a443f9fe1 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ Post-v3.3.0 allows samples to be emitted locally (instead of via IPFIX) in a datapath-specific manner via the new datapath action called "emit_sample". Linux kernel datapath is the first to support this feature. + 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 0c71e354d..e31dabac4 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. * @@ -218,3 +221,113 @@ dpif_lsample_unref(struct dpif_lsample *lsample) dpif_lsample_destroy(lsample); } } + +static int +compare_exporter_list(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 *node; + struct lsample_exporter_node **exporter_list; + 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, compare_exporter_list); + + *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 lsample_exporter_node *node; + 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; + + 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, " Local Sample Group: %"PRIu32"\n", + node->exporter.options.group_id); + ds_put_format(&ds, " Total number of bytes: %"PRIu64"\n", n_bytes); + ds_put_format(&ds, " Total number of packets: %"PRIu64"\n", + n_packets); + } + + 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 2ce096161..eb61769f2 100644 --- a/ofproto/ofproto-dpif-lsample.h +++ b/ofproto/ofproto-dpif-lsample.h @@ -36,6 +36,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 e5a7f0fa5..ccb99c74a 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 Wed Jun 5 20:23:36 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: 1944158 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=JCtkO1nR; 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 4Vvf8828qlz20Q5 for ; Thu, 6 Jun 2024 06:24:40 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id A773541E8A; Wed, 5 Jun 2024 20:24: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 T6YRgCOnWwzf; Wed, 5 Jun 2024 20:24:37 +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 EB4EA424A0 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=JCtkO1nR Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id EB4EA424A0; Wed, 5 Jun 2024 20:24:36 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id DC05EC0077; Wed, 5 Jun 2024 20:24:36 +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 10BCDC0037 for ; Wed, 5 Jun 2024 20:24:35 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 75887423E4 for ; Wed, 5 Jun 2024 20:24:13 +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 ZhPfOrjGCZJ1 for ; Wed, 5 Jun 2024 20:24: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 smtp4.osuosl.org 019DA423D4 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 019DA423D4 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 019DA423D4 for ; Wed, 5 Jun 2024 20:24:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1717619050; 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=ykAgF6WdmFC9swA68/DSYr5LY3+X6Oed/NEi8C/amcY=; b=JCtkO1nRVNJWEkWVhUqmQh+4ybaKDkKvLBNTzbUZmaaXn6wcyk/fvF2AymsyYOrVkiW4zD sK6D9adY3gg0x6Sm/Scr/2ywM8a1ScnOd+H3xkgBwXYoMkFRaoxuhZtqpEBSWJ2FTU9V72 0YdrQ51hzcXbwgh7NSLZ91refTQ8El0= 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-417-nFR2mlFsOZeDuLoL8BNN5w-1; Wed, 05 Jun 2024 16:24:08 -0400 X-MC-Unique: nFR2mlFsOZeDuLoL8BNN5w-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 A36571954208; Wed, 5 Jun 2024 20:24:07 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.193.112]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 67B071956086; Wed, 5 Jun 2024 20:24:05 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Wed, 5 Jun 2024 22:23:36 +0200 Message-ID: <20240605202337.2904041-9-amorenoz@redhat.com> In-Reply-To: <20240605202337.2904041-1-amorenoz@redhat.com> References: <20240605202337.2904041-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [RFC v2 8/9] tests: Add test-psample testing utility. 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" 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 | 282 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 353 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..f04d903b1 --- /dev/null +++ b/tests/test-psample.c @@ -0,0 +1,282 @@ +/* + * 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 uint32_t group_id = 0; +static bool has_filter; +static int psample_family = 0; + +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; + const char *cookie; + + 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) { + cookie = nl_attr_get(attr); + + sample->has_cookie = true; + memcpy(&sample->obs_domain_id, cookie, sizeof sample->obs_domain_id); + memcpy(&sample->obs_point_id, cookie + sizeof sample->obs_domain_id, + sizeof sample->obs_point_id); + } + 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); + + 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); + } + + error = parse_psample(&buf, &sample); + if (error) { + VLOG_ERR_RL(&rl, "error parsing samples: %i", error); + } + + 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 (!ovs_scan(argv[optind], "%"SCNu32, &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 Wed Jun 5 20:23:37 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: 1944159 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=BnW4XjFg; 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 4Vvf8G3vp5z20Wh for ; Thu, 6 Jun 2024 06:24:46 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id DDD38417CB; Wed, 5 Jun 2024 20:24:44 +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 K1X8tS35Q_4Z; Wed, 5 Jun 2024 20:24:44 +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 D411741670 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=BnW4XjFg Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id D411741670; Wed, 5 Jun 2024 20:24:43 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id B9565C0077; Wed, 5 Jun 2024 20:24:43 +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 18A4FC0DD2 for ; Wed, 5 Jun 2024 20:24:42 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id E7161613BA for ; Wed, 5 Jun 2024 20:24:20 +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 FBTq5AJx6mpx for ; Wed, 5 Jun 2024 20:24:18 +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 03AFF6139A 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 03AFF6139A 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=BnW4XjFg 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 03AFF6139A for ; Wed, 5 Jun 2024 20:24:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1717619054; 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=nYNb49JK33ybIEk2WxSY2lJYoM5jBZpcyevRN+8DFas=; b=BnW4XjFgn0K+cQJ738AlzDCIvCekBZaNY7WN2c4FO92iayvDYjAg4TC9rWXFgveLOcFCO9 txak0OqI/RlqxyoQ/b4X8tcFJbl4cVdHdm7jMO0HrOyxhmF0i8wHmqcWbIe8r89NiCi3Ht tEtonj1fI1hGcPlsyuQ9AU5i4ewrORM= 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-163-UZeEn1xZPxCxTvbLYDFNmg-1; Wed, 05 Jun 2024 16:24:11 -0400 X-MC-Unique: UZeEn1xZPxCxTvbLYDFNmg-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 957A51977036; Wed, 5 Jun 2024 20:24:10 +0000 (UTC) Received: from antares.redhat.com (unknown [10.39.193.112]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DB65E1956086; Wed, 5 Jun 2024 20:24:07 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Wed, 5 Jun 2024 22:23:37 +0200 Message-ID: <20240605202337.2904041-10-amorenoz@redhat.com> In-Reply-To: <20240605202337.2904041-1-amorenoz@redhat.com> References: <20240605202337.2904041-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [RFC v2 9/9] tests: Test local sampling. 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" Test simultaneous IPFIX and local sampling including slow-path. Signed-off-by: Adrian Moreno --- tests/system-common-macros.at | 4 ++ tests/system-traffic.at | 105 ++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at index 2a68cd664..22b8885e4 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_EMIT_SAMPLE() +m4_define([OVS_CHECK_EMIT_SAMPLE], + [AT_SKIP_IF([! grep -q "Datapath supports emit_sample" ovs-vswitchd.log])]) diff --git a/tests/system-traffic.at b/tests/system-traffic.at index bd7647cbe..babc56b56 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -8977,3 +8977,108 @@ OVS_WAIT_UNTIL([cat p2.pcap | grep -E "0x0050: *0000 *0000 *5002 *2000 *b85e *00 OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([emit_sample]) +OVS_TRAFFIC_VSWITCHD_START() +OVS_CHECK_EMIT_SAMPLE() + +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") + +NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.2 e4:11:22:33:44:66]) +NS_CHECK_EXEC([at_ns1], [arp -s 10.1.1.1 e4:11:22:33:44:55]) + + +AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg ofproto_dpif_upcall:dbg]) + +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_sample_group=10 \ + -- create Flow_Sample_Collector_Set id=2 bridge=@br0 ipfix=@ipfix, local_sample_group=12], + [0], [ignore]) + +AT_DATA([flows.txt], [dnl +in_port=ovs-p0,ip actions=sample(probability=65535,collector_set_id=1,obs_domain_id=1431655765,obs_point_id=1717986918),output(port=ovs-p1,max_len=100) +in_port=ovs-p1,ip actions=sample(probability=65535,collector_set_id=2,obs_domain_id=2290649224,obs_point_id=2576980377),output(port=ovs-p0,max_len=100) +]) + +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], [group_id=0xa obs_domain=0x55555555,obs_point=0x66666666 .*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2]) +m4_define([SAMPLE2], [group_id=0xc obs_domain=0x88888888,obs_point=0x99999999 .*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1]) +AT_CHECK([grep -E 'SAMPLE1' psample.out >/dev/null]) +AT_CHECK([grep -E 'SAMPLE2' psample.out >/dev/null]) + +AT_CHECK([ovs-ofctl dump-ipfix-flow br0 | sed 's/tx pkts=[[0-9]]*/tx pkts=24/' | sed 's/tx errs=[[0-9]]*/tx errs=0/'], [0], [dnl +NXST_IPFIX_FLOW reply (xid=0x2): 2 ids + id 1: 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 2: 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 + Local Sample Group: 10 + Total number of bytes: 98 + Total number of packets: 1 + +- Collector Set ID: 2 + Local Sample Group: 12 + Total number of bytes: 98 + Total number of packets: 1 +]) + +# Disable trunc feature to force traffic to go through slow path. +AT_CHECK([ovs-appctl dpif/set-dp-features br0 trunc false]) + +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 -3 stdout], [0], [dnl +Datapath actions: emit_sample(group=10,cookie=5555555566666666),userspace(pid=4294967295,flow_sample(probability=65535,collector_set_id=1,obs_domain_id=1431655765,obs_point_id=1717986918,output_port=4294967295)),trunc(100),3 +This flow is handled by the userspace slow path because it: + - Uses action(s) not supported by datapath. +]) + +OVS_DAEMONIZE([ovstest test-psample > psample_slow.out], [psample_slow.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 +]) + +AT_CHECK([grep -E 'SAMPLE1' psample_slow.out >/dev/null]) +AT_CHECK([grep -E 'SAMPLE2' psample_slow.out >/dev/null]) + +AT_CHECK([ovs-ofctl dump-ipfix-flow br0 | sed 's/tx pkts=[[0-9]]*/tx pkts=24/' | sed 's/tx errs=[[0-9]]*/tx errs=0/'], [0], [dnl +NXST_IPFIX_FLOW reply (xid=0x2): 2 ids + id 1: flows=2, current flows=0, sampled pkts=2, ipv4 ok=2, ipv6 ok=0, tx pkts=24 + pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0 + id 2: flows=2, current flows=0, sampled pkts=2, ipv4 ok=2, 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 + Local Sample Group: 10 + Total number of bytes: 196 + Total number of packets: 2 + +- Collector Set ID: 2 + Local Sample Group: 12 + Total number of bytes: 196 + Total number of packets: 2 +]) + +OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"]) +AT_CLEANUP