From patchwork Fri Nov 4 15:49:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Moreno X-Patchwork-Id: 1699661 X-Patchwork-Delegate: dceara@redhat.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=BzgsV548; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4N3lSP0lCXz23ls for ; Sat, 5 Nov 2022 02:49:57 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 6494481E06; Fri, 4 Nov 2022 15:49:55 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 6494481E06 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=BzgsV548 X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CFKQgNpd5_2g; Fri, 4 Nov 2022 15:49:54 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 1907D81466; Fri, 4 Nov 2022 15:49:53 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 1907D81466 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id D27C3C0071; Fri, 4 Nov 2022 15:49:52 +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 219DFC007C for ; Fri, 4 Nov 2022 15:49:51 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 0A67840C73 for ; Fri, 4 Nov 2022 15:49:51 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 0A67840C73 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=BzgsV548 X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 5GyYpe_Bss1c for ; Fri, 4 Nov 2022 15:49:50 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org C5464401E1 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 C5464401E1 for ; Fri, 4 Nov 2022 15:49:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1667576988; 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=gQPAc8vE0lXUd+K8z+plqpxCSKAP5VNPL24+NvsP5l0=; b=BzgsV548vWDWEW/UY1KRd2byHnn2lL2NJ1QlFrs+phPA9fnrdThdpstWw3WitD1XDwTHAQ e0VZbntOSkcbQ8dfXMQB+ObY6rg0V/GEqkMXWJJXR9RUWArJxpw2bZrJyEby2WD+Owlj9/ YaR8uLVZP1QTPS5ToMeqG+YQAdtqIFA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-338-1wqsFalvMYiw4cFLgXedIw-1; Fri, 04 Nov 2022 11:49:47 -0400 X-MC-Unique: 1wqsFalvMYiw4cFLgXedIw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id F3AD5101A528; Fri, 4 Nov 2022 15:49:46 +0000 (UTC) Received: from amorenoz.users.ipa.redhat.com (unknown [10.39.193.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 87F3E1121315; Fri, 4 Nov 2022 15:49:45 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Fri, 4 Nov 2022 16:49:39 +0100 Message-Id: <20221104154941.365187-2-amorenoz@redhat.com> In-Reply-To: <20221104154941.365187-1-amorenoz@redhat.com> References: <20221104154941.365187-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com Subject: [ovs-dev] [PATCH ovn v5 1/3] actions: add sample action X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" sample ovn action encodes into the OFPACT_SAMPLE ovs action. OVN action allows the following parameters: - obs_domain_id: 8-bit integer that identifies the sampling application. This value will be combined with the datapath's tunnel_id to form the final observation_domain_id that will be used in the OVS action as: ObservationDomainID = obs_domain_id << 24 | (dp_key & 0xFFFFFF) - obs_point_id: a 32-bit integer or the $cookie macro that will be expanded into the first 32 bits of the lflow's UUID. - probability: a 16-bit integer that specifies the sampling probability. Specifying 0 has no effect and 65535 means sampling all packets. - collector_set: the 32-bit id that has to be configured in OVS's Flow_Sample_Collector_Set table in order to configure IPFIX sampling. Signed-off-by: Adrian Moreno --- controller/lflow.c | 1 + include/ovn/actions.h | 16 ++++++ lib/actions.c | 120 ++++++++++++++++++++++++++++++++++++++++++ ovn-sb.xml | 52 ++++++++++++++++++ tests/ovn.at | 28 ++++++++++ tests/test-ovn.c | 3 ++ utilities/ovn-trace.c | 2 + 7 files changed, 222 insertions(+) diff --git a/controller/lflow.c b/controller/lflow.c index cc0f31db0..ad316c17f 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -1007,6 +1007,7 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, .group_table = l_ctx_out->group_table, .meter_table = l_ctx_out->meter_table, .lflow_uuid = lflow->header_.uuid, + .dp_key = ldp->datapath->tunnel_key, .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS, .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE, diff --git a/include/ovn/actions.h b/include/ovn/actions.h index d7ee84dac..009487cfc 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -121,6 +121,7 @@ struct ovn_extend_table; OVNACT(COMMIT_ECMP_NH, ovnact_commit_ecmp_nh) \ OVNACT(CHK_ECMP_NH_MAC, ovnact_result) \ OVNACT(CHK_ECMP_NH, ovnact_result) \ + OVNACT(SAMPLE, ovnact_sample) \ /* enum ovnact_type, with a member OVNACT_ for each action. */ enum OVS_PACKED_ENUM ovnact_type { @@ -456,6 +457,18 @@ struct ovnact_lookup_fdb { struct expr_field dst; /* 1-bit destination field. */ }; +/* OVNACT_SAMPLE */ +struct ovnact_sample { + struct ovnact ovnact; + uint16_t probability; /* probability over UINT16_MAX. */ + uint8_t obs_domain_id; /* most significant byte of the + observation domain id. The other 24 bits + will come from the datapath's tunnel key. */ + uint32_t collector_set_id; /* colector_set_id. */ + uint32_t obs_point_id; /* observation point id. */ + bool use_cookie; /* use cookie as obs_point_id */ +}; + /* OVNACT_COMMIT_ECMP_NH. */ struct ovnact_commit_ecmp_nh { struct ovnact ovnact; @@ -785,6 +798,9 @@ struct ovnact_encode_params { /* The logical flow uuid that drove this action. */ struct uuid lflow_uuid; + /* The datapath key. */ + uint32_t dp_key; + /* OVN maps each logical flow table (ltable), one-to-one, onto a physical * OpenFlow flow table (ptable). A number of parameters describe this * mapping and data related to flow tables: diff --git a/lib/actions.c b/lib/actions.c index adbb42db4..cef626f84 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -4279,6 +4279,124 @@ encode_CHECK_OUT_PORT_SEC(const struct ovnact_result *dl, MLF_CHECK_PORT_SEC_BIT, ofpacts); } +static void +format_SAMPLE(const struct ovnact_sample *sample, struct ds *s) +{ + ds_put_format(s, "sample(probability=%"PRId16, sample->probability); + + ds_put_format(s, ",collector_set=%"PRId32, sample->collector_set_id); + ds_put_format(s, ",obs_domain=%"PRId8, sample->obs_domain_id); + if (sample->use_cookie) { + ds_put_cstr(s, ",obs_point=$cookie"); + } else { + ds_put_format(s, ",obs_point=%"PRId32, sample->obs_point_id); + } + ds_put_format(s, ");"); +} + +static void +encode_SAMPLE(const struct ovnact_sample *sample, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + struct ofpact_sample *os = ofpact_put_SAMPLE(ofpacts); + os->probability = sample->probability; + os->collector_set_id = sample->collector_set_id; + os->obs_domain_id = + (sample->obs_domain_id << 24) | (ep->dp_key & 0xFFFFFF); + + if (sample->use_cookie) { + os->obs_point_id = ep->lflow_uuid.parts[0]; + } else { + os->obs_point_id = sample->obs_point_id; + } + os->sampling_port = OFPP_NONE; +} + +static void +parse_sample_arg(struct action_context *ctx, struct ovnact_sample *sample) +{ + if (lexer_match_id(ctx->lexer, "probability")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + if (!action_parse_uint16(ctx, &sample->probability, + "probability")) { + return; + } + } + } else if (lexer_match_id(ctx->lexer, "obs_point")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_MACRO && + !strcmp(ctx->lexer->token.s, "cookie")) { + sample->use_cookie = true; + lexer_get(ctx->lexer); + } else if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + sample->obs_point_id = ntohll(ctx->lexer->token.value.integer); + lexer_get(ctx->lexer); + } else { + lexer_syntax_error(ctx->lexer, + "malformed sample observation_point_id"); + } + } else if (lexer_match_id(ctx->lexer, "obs_domain")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + uint32_t obs_domain = ntohll(ctx->lexer->token.value.integer); + if (obs_domain > UINT8_MAX) { + lexer_syntax_error(ctx->lexer, + "obs_domain must be 8-bit long"); + return; + } + sample->obs_domain_id = obs_domain; + } + lexer_get(ctx->lexer); + } else if (lexer_match_id(ctx->lexer, "collector_set")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + sample->collector_set_id = ntohll(ctx->lexer->token.value.integer); + } + lexer_get(ctx->lexer); + } else { + lexer_syntax_error(ctx->lexer, "unknown argument"); + } +} + +static void +parse_sample(struct action_context *ctx) +{ + struct ovnact_sample * sample = ovnact_put_SAMPLE(ctx->ovnacts); + + if (lexer_match(ctx->lexer, LEX_T_LPAREN)) { + while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) { + parse_sample_arg(ctx, sample); + if (ctx->lexer->error) { + return; + } + lexer_match(ctx->lexer, LEX_T_COMMA); + } + } + if (!sample->probability) { + lexer_error(ctx->lexer, "probability must be greater than zero"); + return; + } +} + +static void +ovnact_sample_free(struct ovnact_sample *sample OVS_UNUSED) +{ +} + static void parse_commit_ecmp_nh(struct action_context *ctx, struct ovnact_commit_ecmp_nh *ecmp_nh) @@ -4790,6 +4908,8 @@ parse_action(struct action_context *ctx) parse_put_fdb(ctx, ovnact_put_PUT_FDB(ctx->ovnacts)); } else if (lexer_match_id(ctx->lexer, "commit_ecmp_nh")) { parse_commit_ecmp_nh(ctx, ovnact_put_COMMIT_ECMP_NH(ctx->ovnacts)); + } else if (lexer_match_id(ctx->lexer, "sample")) { + parse_sample(ctx); } else { lexer_syntax_error(ctx->lexer, "expecting action"); } diff --git a/ovn-sb.xml b/ovn-sb.xml index 315d60853..a09891d10 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -2624,6 +2624,58 @@ tcp.flags = RST; register R is set to 1.

+ +
sample(probability=packets, ...)
+
+

+ This action causes the matched traffic to be sampled using + IPFIX protocol. More information about how per-flow IPFIX sampling + works in OVS can be found in ovs-actions(7) and + ovs-vswitchd.conf.db(5). +

+ +

+ In order to reliably identify each sampled packet when it is + received by the IPFIX collector, this action sets the content of + the ObservationDomainID and + ObservationPointID IPFIX fields (see argument + description below). +

+ +

+ The following key-value arguments are supported: +

+ +
+
probability=packets
+
+ The number of sampled packets out of 65535. It must be greater or + equal to 1. +
+
collector_set=id
+
+ The unsigned 32-bit integer identifier of the sample collector to + send sampled packets to. It must match the value configured in + the Flow_Sample_Collector_Set Table in OVS. + Defaults to 0. +
+
obs_domain=id
+
+ An unsigned 8-bit integer that identifies the sampling + application. It will be placed in the 8 most significant bits of + the ObservationDomainID field of IPFIX samples. + The 24 less significant bits will be automatically filled in with + the datapath key. Defaults to 0. +
+
obs_point=id
+
+ An unsigned 32-bit integer to be used as + ObsservationPointID or the string + @cookie to indicate that the first 32 bits of the + Logical_Flow's UUID shall be used instead. +
+
+
diff --git a/tests/ovn.at b/tests/ovn.at index f8b8db4df..cfcda9a2c 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -2136,6 +2136,34 @@ pop(eth.type); push(abc); Syntax error at `abc' expecting field name. +# sample +sample(probability=100,collector_set=200,obs_domain=0,obs_point=1000); + encodes as sample(probability=100,collector_set_id=200,obs_domain_id=11259375,obs_point_id=1000) + +# sample with obs_domain = 10. Final obs_domain is 0xA << 24 | 0xABCDEF. +sample(probability=100,collector_set=200,obs_domain=10,obs_point=$cookie); + encodes as sample(probability=100,collector_set_id=200,obs_domain_id=179031535,obs_point_id=2863311530) + +sample(probability=10); + formats as sample(probability=10,collector_set=0,obs_domain=0,obs_point=0); + encodes as sample(probability=10,collector_set_id=0,obs_domain_id=11259375,obs_point_id=0) + +sample(probability=10); + formats as sample(probability=10,collector_set=0,obs_domain=0,obs_point=0); + encodes as sample(probability=10,collector_set_id=0,obs_domain_id=11259375,obs_point_id=0) + +sample(probability=0,collector_set=200,obs_domain=0,obs_point=1000); + probability must be greater than zero + +sample(probability=0,collector_set=200,obs_domain=0,obs_point=foo); + Syntax error at `foo' malformed sample observation_point_id. + +sample(probability=0,collector_set=200,obs_domain=300,obs_point=foo); + Syntax error at `300' obs_domain must be 8-bit long. + +sample(probability=10,foo=bar,obs_domain=0,obs_point=1000); + Syntax error at `foo' unknown argument. + # Miscellaneous negative tests. ; Syntax error at `;'. diff --git a/tests/test-ovn.c b/tests/test-ovn.c index a241f150d..fd580b5df 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -1355,6 +1355,9 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) .common_nat_ct_zone = MFF_LOG_DNAT_ZONE, .in_port_sec_ptable = OFTABLE_CHK_IN_PORT_SEC, .out_port_sec_ptable = OFTABLE_CHK_OUT_PORT_SEC, + .lflow_uuid.parts = + { 0xaaaaaaaa, 0xbbbbbbbb, 0xcccccccc, 0xdddddddd}, + .dp_key = 0xabcdef, }; struct ofpbuf ofpacts; ofpbuf_init(&ofpacts, 0); diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 6fa5137d9..ada562e41 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -3290,6 +3290,8 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, break; case OVNACT_CHK_ECMP_NH: break; + case OVNACT_SAMPLE: + break; } } ofpbuf_uninit(&stack); From patchwork Fri Nov 4 15:49:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Moreno X-Patchwork-Id: 1699662 X-Patchwork-Delegate: dceara@redhat.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Rv0PtTkg; dkim-atps=neutral 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 (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4N3lSc1qkhz23lv for ; Sat, 5 Nov 2022 02:50:08 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 277F740CF6; Fri, 4 Nov 2022 15:50:05 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 277F740CF6 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=Rv0PtTkg X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PF5OOMO3e3l0; Fri, 4 Nov 2022 15:50:01 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id 1A1A640CA1; Fri, 4 Nov 2022 15:50:00 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 1A1A640CA1 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E3C5FC0033; Fri, 4 Nov 2022 15:49:59 +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 12857C002D for ; Fri, 4 Nov 2022 15:49:58 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 64A6661122 for ; Fri, 4 Nov 2022 15:49:57 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 64A6661122 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=Rv0PtTkg X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id GKvibmYS9K6H for ; Fri, 4 Nov 2022 15:49:53 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org F156661113 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id F156661113 for ; Fri, 4 Nov 2022 15:49:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1667576992; 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=xnXvQuptPMEl7KH6gOPk7TV0tg4HMhDKyKihku5Ilok=; b=Rv0PtTkgvv2W08F4MsI5vURaFSQPjtJlT/8FaAMyqJqjinPnL3xvG13/f4EXv1JPIddUwT 8j6MPl37H6B1GRe64pTix1vzfX1WbPmx+K+yE9zMa6e9Tr7PX+bPtZDY5TVw1DMsI8tqRi ws6yP9gU8bn/seX42K1EzQwJVqvYZW8= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-492-g5sXYD-BP8emdCDd8nczpA-1; Fri, 04 Nov 2022 11:49:48 -0400 X-MC-Unique: g5sXYD-BP8emdCDd8nczpA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A0DCD1C0BC61; Fri, 4 Nov 2022 15:49:48 +0000 (UTC) Received: from amorenoz.users.ipa.redhat.com (unknown [10.39.193.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 42BF41121315; Fri, 4 Nov 2022 15:49:47 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Fri, 4 Nov 2022 16:49:40 +0100 Message-Id: <20221104154941.365187-3-amorenoz@redhat.com> In-Reply-To: <20221104154941.365187-1-amorenoz@redhat.com> References: <20221104154941.365187-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com Subject: [ovs-dev] [PATCH ovn v5 2/3] northd: make default drops explicit 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" By default, traffic that doesn't match any configured flow will be dropped. But having that behavior implicit makes those drops more difficult to visualize. Make default drops explicit both as default logical flows and as default openflow flows (e.g: for physical tables). Signed-off-by: Adrian Moreno --- controller/physical.c | 45 +++++++ northd/northd.c | 34 +++++- northd/ovn-northd.8.xml | 40 ++++++- tests/ovn-northd.at | 84 +++++++++++++ tests/ovn.at | 256 +++++++++++++++++++++++++++++++++++----- 5 files changed, 421 insertions(+), 38 deletions(-) diff --git a/controller/physical.c b/controller/physical.c index 705146316..415d16b76 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -833,6 +833,17 @@ put_zones_ofpacts(const struct zone_ids *zone_ids, struct ofpbuf *ofpacts_p) } } +static void +add_default_drop_flow(uint8_t table_id, + struct ovn_desired_flow_table *flow_table) +{ + struct match match = MATCH_CATCHALL_INITIALIZER; + struct ofpbuf ofpacts; + ofpbuf_init(&ofpacts, 0); + ofctrl_add_flow(flow_table, table_id, 0, 0, &match, + &ofpacts, hc_uuid); +} + static void put_local_common_flows(uint32_t dp_key, const struct sbrec_port_binding *pb, @@ -2114,6 +2125,13 @@ physical_run(struct physical_ctx *p_ctx, } } + /* Table 0, priority 0. + * ====================== + * + * Drop packets tha do not match any tunnel in_port. + */ + add_default_drop_flow(OFTABLE_PHY_TO_LOG, flow_table); + /* Table 37, priority 150. * ======================= * @@ -2159,6 +2177,13 @@ physical_run(struct physical_ctx *p_ctx, ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 0, 0, &match, &ofpacts, hc_uuid); + /* Table 38, priority 0. + * ====================== + * + * Drop packets that do not match previous flows. + */ + add_default_drop_flow(OFTABLE_LOCAL_OUTPUT, flow_table); + /* Table 39, Priority 0. * ======================= * @@ -2185,5 +2210,25 @@ physical_run(struct physical_ctx *p_ctx, ofctrl_add_flow(flow_table, OFTABLE_SAVE_INPORT, 0, 0, &match, &ofpacts, hc_uuid); + /* Table 65, priority 0. + * ====================== + * + * Drop packets that do not match previous flows. + */ + add_default_drop_flow(OFTABLE_LOG_TO_PHY, flow_table); + + /* Table 68, priority 0. + * ====================== + * + * Drop packets that do not match previous flows. + */ + add_default_drop_flow(OFTABLE_CHK_LB_HAIRPIN, flow_table); + + /* Table 70, priority 0. + * ====================== + * + * Drop packets that do not match previous flows. + */ + add_default_drop_flow(OFTABLE_CT_SNAT_HAIRPIN, flow_table); ofpbuf_uninit(&ofpacts); } diff --git a/northd/northd.c b/northd/northd.c index b7388afc5..4b1829d37 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -5155,6 +5155,16 @@ ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od, io_port, ctrl_meter, stage_hint, where, hash); } +static void +__ovn_lflow_add_default_drop(struct hmap *lflow_map, + struct ovn_datapath *od, + enum ovn_stage stage, + const char *where) +{ + ovn_lflow_add_at(lflow_map, od, stage, 0, "1", "drop;", + NULL, NULL, NULL, where ); +} + /* Adds a row with the specified contents to the Logical_Flow table. */ #define ovn_lflow_add_with_hint__(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, \ ACTIONS, IN_OUT_PORT, CTRL_METER, \ @@ -5167,6 +5177,10 @@ ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od, ovn_lflow_add_at(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, \ NULL, NULL, STAGE_HINT, OVS_SOURCE_LOCATOR) +#define ovn_lflow_add_default_drop(LFLOW_MAP, OD, STAGE) \ + __ovn_lflow_add_default_drop(LFLOW_MAP, OD, STAGE, OVS_SOURCE_LOCATOR) + + /* This macro is similar to ovn_lflow_add_with_hint, except that it requires * the IN_OUT_PORT argument, which tells the lport name that appears in the * MATCH, which helps ovn-controller to bypass lflows parsing when the lport is @@ -10974,6 +10988,9 @@ build_adm_ctrl_flows_for_lrouter( * Broadcast/multicast source address is invalid. */ ovn_lflow_add(lflows, od, S_ROUTER_IN_ADMISSION, 100, "vlan.present || eth.src[40]", "drop;"); + + /* Default action for L2 security is to drop. */ + ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_ADMISSION); } } @@ -11215,6 +11232,8 @@ build_neigh_learning_flows_for_lrouter( "nd_ns", "put_nd(inport, ip6.src, nd.sll); next;", copp_meter_get(COPP_ND_NS, od->nbr->copp, meter_groups)); + + ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR); } } @@ -11491,6 +11510,8 @@ build_static_route_flows_for_lrouter( const struct hmap *bfd_connections) { if (od->nbr) { + ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_IP_ROUTING_ECMP); + ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_IP_ROUTING); ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING_ECMP, 150, REG_ECMP_GROUP_ID" == 0", "next;"); @@ -11662,6 +11683,7 @@ build_ingress_policy_flows_for_lrouter( REG_ECMP_GROUP_ID" = 0; next;"); ovn_lflow_add(lflows, od, S_ROUTER_IN_POLICY_ECMP, 150, REG_ECMP_GROUP_ID" == 0", "next;"); + ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_POLICY_ECMP); /* Convert routing policies to flows. */ uint16_t ecmp_group_id = 1; @@ -11694,11 +11716,13 @@ build_arp_resolve_flows_for_lrouter( ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 500, "ip4.mcast || ip6.mcast", "next;"); - ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 0, "ip4", + ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 1, "ip4", "get_arp(outport, " REG_NEXT_HOP_IPV4 "); next;"); - ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 0, "ip6", + ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 1, "ip6", "get_nd(outport, " REG_NEXT_HOP_IPV6 "); next;"); + + ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_ARP_RESOLVE); } } @@ -11824,9 +11848,9 @@ build_arp_resolve_flows_for_lrouter_port( * in stage "lr_in_ip_input" but traffic that could have been unSNATed * but didn't match any existing session might still end up here. * - * Priority 1. + * Priority 2. */ - build_lrouter_drop_own_dest(op, S_ROUTER_IN_ARP_RESOLVE, 1, true, + build_lrouter_drop_own_dest(op, S_ROUTER_IN_ARP_RESOLVE, 2, true, lflows); } else if (op->od->n_router_ports && !lsp_is_router(op->nbsp) && strcmp(op->nbsp->type, "virtual")) { @@ -12428,6 +12452,8 @@ build_egress_delivery_flows_for_lrouter_port( ds_put_format(match, "outport == %s", op->json_key); ovn_lflow_add(lflows, op->od, S_ROUTER_OUT_DELIVERY, 100, ds_cstr(match), "output;"); + + ovn_lflow_add_default_drop(lflows, op->od, S_ROUTER_OUT_DELIVERY); } } diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index a70f2e678..cb996279f 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -2151,6 +2151,11 @@ output; the NAT rule resides.

+ +
  • + A priority-0 logical flow that matches all packets not already handled + (match 1) and drops them (action drop;). +
  • @@ -2358,6 +2363,11 @@ next; applies the action put_nd(inport, ip6.src, nd.sll); next; + +

  • + A priority-0 logical flow that matches all packets not already handled + (match 1) and drops them (action drop;). +
  • Ingress Table 3: IP Input

    @@ -3739,6 +3749,11 @@ reg8[0..15] = GID; select(reg8[16..31], MID1, MID2, ...); + +
  • + A priority-0 logical flow that matches all packets not already handled + (match 1) and drops them (action drop;). +
  • Ingress Table 12: IP_ROUTING_ECMP

    @@ -3791,6 +3806,11 @@ eth.src = E; outport = P; + +
  • + A priority-0 logical flow that matches all packets not already handled + (match 1) and drops them (action drop;). +
  • Ingress Table 13: Router policies

    @@ -3907,6 +3927,11 @@ outport = P which the nexthop is reachable.

    + +
  • + A priority-0 logical flow that matches all packets not already handled + (match 1) and drops them (action drop;). +
  • Ingress Table 15: ARP/ND Resolution

    @@ -4082,16 +4107,22 @@ outport = P

    - A priority-1 logical flow with match ip4.dst = {..} + A priority-2 logical flow with match ip4.dst = {..} matches on traffic destined to router owned IPv4 addresses which are also SNAT IPs. This flow has action drop;.

    - A priority-1 logical flow with match ip6.dst = {..} + A priority-2 logical flow with match ip6.dst = {..} matches on traffic destined to router owned IPv6 addresses which are also SNAT IPs. This flow has action drop;.

    + +

    + A priority-0 logical that flow matches all packets not already + handled (match 1) and drops them + (action drop;). +

  • @@ -4808,6 +4839,11 @@ clone { Priority-100 logical flows that match packets on each enabled logical router port, with action output;.
  • +
  • + A priority-0 logical flow that matches all packets not already + handled (match 1) and drops them + (action drop;). +
  • diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 4f399eccb..7dba12d0b 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -2850,6 +2850,7 @@ AT_CAPTURE_FILE([lr0flows3]) AT_CHECK([grep "lr_in_policy" lr0flows3 | sed 's/table=../table=??/' | sort], [0], [dnl table=??(lr_in_policy ), priority=0 , match=(1), action=(reg8[[0..15]] = 0; next;) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.3), action=(reg8[[0..15]] = 1; reg8[[16..31]] = select(1, 2);) + table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) table=??(lr_in_policy_ecmp ), priority=150 , match=(reg8[[0..15]] == 0), action=(next;) @@ -2865,6 +2866,7 @@ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == /' | sed 's/table table=??(lr_in_policy ), priority=0 , match=(1), action=(reg8[[0..15]] = ; next;) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.3), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2);) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.4), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2, 3);) + table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) @@ -2884,6 +2886,7 @@ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == /' | sed 's/table table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.3), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2);) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.4), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2, 3);) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.5), action=(reg0 = 172.168.0.110; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg8[[0..15]] = ; next;) + table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) @@ -2902,6 +2905,7 @@ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == /' | sed 's/table table=??(lr_in_policy ), priority=0 , match=(1), action=(reg8[[0..15]] = ; next;) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.4), action=(reg8[[0..15]] = ; reg8[[16..31]] = select(1, 2, 3);) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.5), action=(reg0 = 172.168.0.110; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg8[[0..15]] = ; next;) + table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 1), action=(reg0 = 172.168.0.101; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 2), action=(reg0 = 172.168.0.102; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) table=??(lr_in_policy_ecmp ), priority=100 , match=(reg8[[0..15]] == && reg8[[16..31]] == 3), action=(reg0 = 172.168.0.103; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; next;) @@ -2917,6 +2921,7 @@ sed 's/reg8\[[0..15\]] = [[0-9]]*/reg8\[[0..15\]] = /' | \ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == /' | sed 's/table=../table=??/' | sort], [0], [dnl table=??(lr_in_policy ), priority=0 , match=(1), action=(reg8[[0..15]] = ; next;) table=??(lr_in_policy ), priority=10 , match=(ip4.src == 10.0.0.5), action=(reg0 = 172.168.0.110; reg1 = 172.168.0.100; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; flags.loopback = 1; reg8[[0..15]] = ; next;) + table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) table=??(lr_in_policy_ecmp ), priority=150 , match=(reg8[[0..15]] == ), action=(next;) ]) @@ -2928,6 +2933,7 @@ AT_CHECK([grep "lr_in_policy" lr0flows3 | \ sed 's/reg8\[[0..15\]] = [[0-9]]*/reg8\[[0..15\]] = /' | \ sed 's/reg8\[[0..15\]] == [[0-9]]*/reg8\[[0..15\]] == /' | sed 's/table=../table=??/' | sort], [0], [dnl table=??(lr_in_policy ), priority=0 , match=(1), action=(reg8[[0..15]] = ; next;) + table=??(lr_in_policy_ecmp ), priority=0 , match=(1), action=(drop;) table=??(lr_in_policy_ecmp ), priority=150 , match=(reg8[[0..15]] == ), action=(next;) ]) @@ -5762,6 +5768,7 @@ ovn-sbctl dump-flows lr0 > lr0flows AT_CHECK([grep -e "lr_in_ip_routing.*select" lr0flows |sort], [0], [dnl ]) AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed 's/table=../table=??/' |sort], [0], [dnl + table=??(lr_in_ip_routing_ecmp), priority=0 , match=(1), action=(drop;) table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]] == 0), action=(next;) ]) @@ -5772,6 +5779,7 @@ AT_CHECK([grep -e "lr_in_ip_routing.*select" lr0flows | sed 's/table=../table=?? table=??(lr_in_ip_routing ), priority=97 , match=(reg7 == 0 && ip4.dst == 1.0.0.1/32), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; reg8[[16..31]] = select(1, 2);) ]) AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed 's/192\.168\.0\..0/192.168.0.??/' | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_in_ip_routing_ecmp), priority=0 , match=(1), action=(drop;) table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; next;) table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; next;) table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]] == 0), action=(next;) @@ -5815,6 +5823,7 @@ AT_CHECK([grep -e "lr_in_ip_routing.*select" lr0flows | sed 's/table=../table=?? table=??(lr_in_ip_routing ), priority=97 , match=(reg7 == 0 && ip4.dst == 1.0.0.1/32), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; reg8[[16..31]] = select(1, 2);) ]) AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed 's/192\.168\.0\..0/192.168.0.??/' | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(lr_in_ip_routing_ecmp), priority=0 , match=(1), action=(drop;) table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; next;) table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]] == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg1 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; next;) table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]] == 0), action=(next;) @@ -6896,6 +6905,7 @@ AT_CHECK([cat lrflows | grep -e lr_in_lookup_neighbor -e lr_in_learn_neighbor | table=1 (lr_in_lookup_neighbor), priority=100 , match=(arp.op == 2), action=(reg9[[2]] = lookup_arp(inport, arp.spa, arp.sha); next;) table=1 (lr_in_lookup_neighbor), priority=100 , match=(nd_na), action=(reg9[[2]] = lookup_nd(inport, nd.target, nd.tll); next;) table=1 (lr_in_lookup_neighbor), priority=100 , match=(nd_ns), action=(reg9[[2]] = lookup_nd(inport, ip6.src, nd.sll); next;) + table=2 (lr_in_learn_neighbor), priority=0 , match=(1), action=(drop;) table=2 (lr_in_learn_neighbor), priority=100 , match=(reg9[[2]] == 1), action=(next;) table=2 (lr_in_learn_neighbor), priority=90 , match=(arp), action=(put_arp(inport, arp.spa, arp.sha); next;) table=2 (lr_in_learn_neighbor), priority=90 , match=(nd_na), action=(put_nd(inport, nd.target, nd.tll); next;) @@ -7929,3 +7939,77 @@ AT_CHECK([grep "lr_in_arp_resolve" R1flows | grep priority=90 | sort], [0], [dnl AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([Check default drop]) +AT_KEYWORDS([drop]) + +# Check that there is an explicit drop lflow in all tables. +check_default_lflow() { + dps=$(ovn-sbctl --bare --columns=_uuid list Datapath_Binding | xargs) + for dp in $dps; do + for pipeline in ingress egress; do + for table in $(ovn-sbctl --bare --columns=table_id find Logical_Flow logical_datapath="$dp" pipeline="$pipeline" | xargs | sort | uniq); do + echo "Checking if datapath $dp pipeline $pipeline table $table has a default action" + AT_CHECK([ovn-sbctl --columns=_uuid find Logical_Flow logical_datapath="$dp" pipeline="$pipeline" table_id=$table match="1" priority">="0 | wc -l | tr -d "\n\r" ], [0], [1], [ignore], + [echo "Datapath $dp pipeline $pipeline table $table does not have a default action"]) + done + done + done +} + +ovn_start + +# Create LS + LR +check ovn-nbctl --wait=sb \ + -- lr-add R1 \ + -- lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24 \ + -- ls-add S1 \ + -- lsp-add S1 S1-R1 \ + -- lsp-set-type S1-R1 router \ + -- lsp-set-addresses S1-R1 02:ac:10:01:00:01 \ + -- lsp-set-options S1-R1 router-port=R1-S1 \ + -- lsp-add S1 p1 \ + -- lsp-set-addresses p1 "02:ac:10:01:00:0a 172.16.1.100" + +check_default_lflow + +# Add stateless ACL +check ovn-nbctl --wait=sb \ + -- acl-add S1 from-lport 100 'inport=p1 && ip4' allow-stateless + +check_default_lflow + +check ovn-nbctl --wait=sb acl-del S1 + + +# Add stateful ACL +check ovn-nbctl --wait=sb \ + -- acl-add S1 from-lport 2 "udp" allow-related + +check_default_lflow + +check ovn-nbctl --wait=sb acl-del S1 + +# Add LB +check ovn-nbctl --wait=sb \ + -- lb-add lb "10.0.0.1" "10.0.0.2" \ + -- ls-lb-add S1 lb + +check_default_lflow + +# Check LB + stateless ACL +check ovn-nbctl --wait=sb \ + -- acl-add S1 from-lport 100 'inport=p1 && ip4' allow-stateless +check_default_lflow + +check ovn-nbctl --wait=sb acl-del S1 + +# Check LB + statelful ACL +check ovn-nbctl --wait=sb \ + -- acl-add S1 from-lport 2 "udp" allow-related + +check_default_lflow + +AT_CLEANUP +]) diff --git a/tests/ovn.at b/tests/ovn.at index cfcda9a2c..0a6489ea0 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -12707,7 +12707,7 @@ for i in 1 2; do done done -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int |awk '/table=65/{print substr($8, 16, length($8))}' |sort -n], [0], [dnl +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int |awk '/table=65/ && !/actions=drop/{print substr($8, 16, length($8))}' |sort -n], [0], [dnl 10 11 ]) @@ -12716,7 +12716,7 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int |awk '/table=65/{print substr($8, 1 as hv1 check ovs-vsctl del-port vif01 check ovn-nbctl --wait=hv sync -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int |awk '/table=65/{print substr($8, 16, length($8))}' |sort -n], [0], [dnl +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int |awk '/table=65/ && !/actions=drop/{print substr($8, 16, length($8))}' |sort -n], [0], [dnl 11 ]) @@ -12724,7 +12724,7 @@ as hv1 check ovs-vsctl add-port br-int vif01 \ -- set Interface vif01 external-ids:iface-id=lp01 check ovn-nbctl --wait=hv sync -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int |awk '/table=65/{print substr($8, 16, length($8))}' |sort -n], [0], [dnl +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int |awk '/table=65/ && !/actions=drop/{print substr($8, 16, length($8))}' |sort -n], [0], [dnl 2 11 ]) @@ -27832,7 +27832,7 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep "actions=controller" | grep ]) # The packet should've been dropped in the lr_in_arp_resolve stage. -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=23, n_packets=1,.* priority=1,ip,metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=23, n_packets=1,.* priority=2,ip,metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl 1 ]) @@ -28588,31 +28588,36 @@ check ovn-nbctl lb-add lb-ipv4-udp 88.88.88.88:4040 42.42.42.1:2021 udp check ovn-nbctl lb-add lb-ipv6-tcp [[8800::0088]]:8080 [[4200::1]]:4041 tcp check ovn-nbctl --wait=hv lb-add lb-ipv6-udp [[8800::0088]]:4040 [[4200::1]]:2021 udp -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | grep -v NXST], [1], [dnl +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop ]) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | grep -v NXST], [1], [dnl +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop ]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | grep -v NXST], [1], [dnl +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | grep -v NXST], [1], [dnl +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop ]) check ovn-nbctl --wait=hv ls-lb-add sw0 lb-ipv4-tcp OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 1] + [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 2] ) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) ]) @@ -28621,25 +28626,29 @@ NXST_FLOW reply (xid=0x8): ]) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) ]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | grep -v NXST], [1], [dnl +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | grep -v NXST], [1], [dnl +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop ]) check ovn-nbctl lb-add lb-ipv4-tcp 88.88.88.90:8080 42.42.42.42:4041,52.52.52.52:4042 tcp OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 3] + [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 4] ) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28650,17 +28659,20 @@ NXST_FLOW reply (xid=0x8): ]) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) ]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | grep -v NXST], [1], [dnl +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | grep -v NXST], [1], [dnl +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop ]) @@ -28669,10 +28681,11 @@ check ovn-nbctl lsp-add sw0 sw0-p2 OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw0-p2) = xup]) OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 3] + [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 4] ) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28682,6 +28695,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) ]) @@ -28689,14 +28703,15 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep - check ovn-nbctl --wait=hv ls-lb-add sw0 lb-ipv4-udp OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 4] + [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 5] ) OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 4] + [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 5] ) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28707,12 +28722,14 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) table=70, priority=100,udp,reg1=0x58585858,reg2=0xfc8/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28723,6 +28740,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) table=70, priority=100,udp,reg1=0x58585858,reg2=0xfc8/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) @@ -28731,14 +28749,15 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep - check ovn-nbctl --wait=hv ls-lb-add sw0 lb-ipv6-tcp OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 5] + [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 6] ) OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 5] + [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 6] ) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28750,6 +28769,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) @@ -28757,6 +28777,7 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep - ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28768,6 +28789,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) @@ -28777,14 +28799,15 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep - check ovn-nbctl --wait=hv ls-lb-add sw0 lb-ipv6-udp OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 6] + [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 7] ) OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 6] + [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 7] ) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28797,6 +28820,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) @@ -28805,6 +28829,7 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep - ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28817,6 +28842,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) @@ -28829,14 +28855,15 @@ check ovn-nbctl --wait=hv ls-lb-add sw1 lb-ipv6-udp # Number of hairpin flows shouldn't change as it doesn't depend on how many # datapaths the LB is applied. OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 6] + [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 7] ) OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 6] + [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 7] ) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28849,6 +28876,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) @@ -28857,6 +28885,7 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep - ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28869,6 +28898,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp,reg1=0x58585858,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90)) table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) @@ -28890,6 +28920,7 @@ check ovn-sbctl \ -- remove load_balancer lb-ipv6-udp options hairpin_orig_tuple OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_state=+trk+dnat,ct_mark=0x2/0x2,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_state=+trk+dnat,ct_mark=0x2/0x2,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_state=+trk+dnat,ct_mark=0x2/0x2,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28902,6 +28933,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) table=70, priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) table=70, priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) @@ -28910,6 +28942,7 @@ OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_a ]) OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_state=+trk+dnat,ct_mark=0x2/0x2,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_state=+trk+dnat,ct_mark=0x2/0x2,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_state=+trk+dnat,ct_mark=0x2/0x2,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28922,6 +28955,7 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], [1], [dnl ]) OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) table=70, priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) table=70, priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) @@ -28941,7 +28975,7 @@ OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw0-p2) = xdown]) as hv2 ovn-appctl -t ovn-controller recompute OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 0] + [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 1] ) OVS_WAIT_UNTIL( @@ -28949,24 +28983,25 @@ OVS_WAIT_UNTIL( ) OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=70 | grep -c -v NXST) -eq 0] + [test $(as hv2 ovs-ofctl dump-flows br-int table=70 | grep -c -v NXST) -eq 1] ) OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 6] + [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 7] ) check ovn-nbctl --wait=hv lb-del lb-ipv4-tcp OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 3] + [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 4] ) OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 0] + [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 1] ) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=68, priority=0 actions=drop table=68, priority=100,ct_mark=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) table=68, priority=100,ct_mark=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021 actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]]) @@ -28977,6 +29012,7 @@ NXST_FLOW reply (xid=0x8): ]) AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | grep -v NXST], [0], [dnl + table=70, priority=0 actions=drop table=70, priority=100,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) table=70, priority=100,udp,reg1=0x58585858,reg2=0xfc8/0xffff actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88)) table=70, priority=100,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88 actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88)) @@ -28986,7 +29022,7 @@ check ovn-nbctl --wait=hv ls-del sw0 check ovn-nbctl --wait=hv ls-del sw1 OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 0] + [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 1] ) OVS_WAIT_UNTIL( @@ -28994,11 +29030,11 @@ OVS_WAIT_UNTIL( ) OVS_WAIT_UNTIL( - [test $(as hv1 ovs-ofctl dump-flows br-int table=70 | grep -c -v NXST) -eq 0] + [test $(as hv1 ovs-ofctl dump-flows br-int table=70 | grep -c -v NXST) -eq 1] ) OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 0] + [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) -eq 1] ) OVS_WAIT_UNTIL( @@ -29006,7 +29042,7 @@ OVS_WAIT_UNTIL( ) OVS_WAIT_UNTIL( - [test $(as hv2 ovs-ofctl dump-flows br-int table=70 | grep -c -v NXST) -eq 0] + [test $(as hv2 ovs-ofctl dump-flows br-int table=70 | grep -c -v NXST) -eq 1] ) OVN_CLEANUP([hv1], [hv2]) @@ -33003,3 +33039,159 @@ check ovn-nbctl --wait=hv sync OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([Check default openflow flows]) +ovn_start + +# Check that every table has a default (i.e: priority=0) flow. +# Technically a default flow would have no match but we allow the datapath +# match (metadata=0xXX) to be present. +check_default_flows() { + ovs-ofctl dump-flows br-int > oflows + AT_CAPTURE_FILE([oflows]) + for table in $(grep -oP "table=\K\d*, " oflows | sort -n | uniq); do + AT_CHECK([grep -qe "table=$table.* priority=0\(,metadata=0x\w*\)\? actions" oflows], [0], [ignore], [ignore], [echo "Table $table does not contain a default action"]) + done +} + +# Logical network: +# Two LRs - R1 and R2 that are connected to each other as peers in 20.0.0.0/24 +# network. R1 has a switchs ls1 (191.168.1.0/24) connected to it. +# R2 has ls2 (172.16.1.0/24) connected to it. + +ls1_lp1_mac="f0:00:00:01:02:03" +rp_ls1_mac="00:00:00:01:02:03" +rp_ls2_mac="00:00:00:01:02:04" +ls2_lp1_mac="f0:00:00:01:02:04" + +ls1_lp1_ip="192.168.1.2" +ls2_lp1_ip="172.16.1.2" + +ovn-nbctl lr-add R1 +ovn-nbctl ls-add ls1 +ovn-nbctl ls-add ls2 + +# Connect ls1 to R1 +ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24 + +ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \ + options:router-port=ls1 addresses=\"$rp_ls1_mac\" + +# Connect ls2 to R1 +ovn-nbctl lrp-add R1 ls2 $rp_ls2_mac 172.16.1.1/24 + +ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \ + options:router-port=ls2 addresses=\"$rp_ls2_mac\" + +# Create logical port ls1-lp1 in ls1 +ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip" + +# Create logical port ls2-lp1 in ls2 +ovn-nbctl lsp-add ls2 ls2-lp1 \ +-- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +sim_add hv2 +as hv2 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +ovs-vsctl -- add-port br-int hv2-vif1 -- \ + set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \ + options:tx_pcap=hv2/vif1-tx.pcap \ + options:rxq_pcap=hv2/vif1-rx.pcap \ + ofport-request=1 + + +# Allow some time for ovn-northd and ovn-controller to catch up. +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +as hv1 +check_default_flows +as hv2 +check_default_flows + +# Add stateless ACL +check ovn-nbctl --wait=sb \ + -- acl-add ls1 from-lport 100 'ip4' allow-stateless +check ovn-nbctl --wait=sb \ + -- acl-add ls2 from-lport 100 'ip4' allow-stateless + +as hv1 +check_default_flows +as hv2 +check_default_flows + +check ovn-nbctl --wait=sb acl-del ls1 +check ovn-nbctl --wait=sb acl-del ls2 + +# Add stateful ACL +check ovn-nbctl --wait=sb \ + -- acl-add ls1 from-lport 100 "udp" allow-related +check ovn-nbctl --wait=sb \ + -- acl-add ls2 from-lport 100 "udp" allow-related + +as hv1 +check_default_flows +as hv2 +check_default_flows + +check ovn-nbctl --wait=sb acl-del ls1 +check ovn-nbctl --wait=sb acl-del ls2 + +# Add LB +check ovn-nbctl --wait=sb \ + -- lb-add lb1 "10.0.0.1" "10.0.0.2" \ + -- ls-lb-add ls1 lb1 + +check ovn-nbctl --wait=sb \ + -- lb-add lb2 "10.0.1.1" "10.0.1.2" \ + -- ls-lb-add ls2 lb2 + +as hv1 +check_default_flows +as hv2 +check_default_flows + +# LB + stateless ACL +check ovn-nbctl --wait=sb \ + -- acl-add ls1 from-lport 100 'ip4' allow-stateless +check ovn-nbctl --wait=sb \ + -- acl-add ls2 from-lport 100 'ip4' allow-stateless + +as hv1 +check_default_flows +as hv2 +check_default_flows + +check ovn-nbctl --wait=sb acl-del ls1 +check ovn-nbctl --wait=sb acl-del ls2 + +# LB + stateful ACL +check ovn-nbctl --wait=sb \ + -- acl-add ls1 from-lport 100 "udp" allow-related +check ovn-nbctl --wait=sb \ + -- acl-add ls2 from-lport 100 "udp" allow-related + +as hv1 +check_default_flows +as hv2 +check_default_flows + +OVN_CLEANUP([hv1],[hv2]) +AT_CLEANUP +]) From patchwork Fri Nov 4 15:49:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Moreno X-Patchwork-Id: 1699663 X-Patchwork-Delegate: dceara@redhat.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=R9mFOK/e; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4N3lSl19N9z23lQ for ; Sat, 5 Nov 2022 02:50:15 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 54A9181FAE; Fri, 4 Nov 2022 15:50:12 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 54A9181FAE 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=R9mFOK/e X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aXzjkzjD8uh6; Fri, 4 Nov 2022 15:50:07 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id A755481F1D; Fri, 4 Nov 2022 15:50:03 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org A755481F1D Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 36A1EC0083; Fri, 4 Nov 2022 15:50:01 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1206EC0033 for ; Fri, 4 Nov 2022 15:49:59 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 92D174008E for ; Fri, 4 Nov 2022 15:49:57 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 92D174008E 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=R9mFOK/e X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id H2wFpqMOafFB for ; Fri, 4 Nov 2022 15:49:54 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 8FE7241943 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp4.osuosl.org (Postfix) with ESMTPS id 8FE7241943 for ; Fri, 4 Nov 2022 15:49:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1667576993; 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=zemb4dGwxkEZ4PBLYpSmd4YBOEupZ+0uP3L/oy5jdgk=; b=R9mFOK/eJ/0YNAknY+LnV1QqSRAyKWhV2Ej0jcZ5TLuSXmCcMuE+qs8WTaMxKGMu/3Yqib VSfIHH+Odar4XTWBefK/ciem/irLTLLypgSQA7HWKCQ6T+J0X5NGcITazvUJuXgt2nJ+ey 2if6F9ZPk2wTwn/SlTfJMFrhRux8b7c= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-552-jXPD91L2Md2LPKWKHxw1Ig-1; Fri, 04 Nov 2022 11:49:50 -0400 X-MC-Unique: jXPD91L2Md2LPKWKHxw1Ig-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 1ADA51C0BC61; Fri, 4 Nov 2022 15:49:50 +0000 (UTC) Received: from amorenoz.users.ipa.redhat.com (unknown [10.39.193.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id ED0681121315; Fri, 4 Nov 2022 15:49:48 +0000 (UTC) From: Adrian Moreno To: dev@openvswitch.org Date: Fri, 4 Nov 2022 16:49:41 +0100 Message-Id: <20221104154941.365187-4-amorenoz@redhat.com> In-Reply-To: <20221104154941.365187-1-amorenoz@redhat.com> References: <20221104154941.365187-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com Subject: [ovs-dev] [PATCH ovn v5 3/3] northd: add drop 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" Two new options are added to NB_Global table that enable drop sampling by specifying the collector_set_id and the obs_domain_id of the sample actions added to all drop flows. For drops coming from an lflow, the sample has the following fields: - obs_domain_id (32-bit): obs_domain_id << 8 | datapath_key - 8 most significant bits: the obs_domain_id specified in the NB_Global options. - 24 least significant bits: the datapath key. - obs_point_id: the cookie (first 32-bits of the lflow's UUID). For drops that are inserted by ovn-controller without any associated lflow, the sample will have the follwing fields: - obs_domain_id (32-bit): obs_domain_id << 8 - 8 most significant bits: the obs_domain_id specified in the NB_Global options. - 24 least significant bits: 0. - obs_point_id: The openflow table number. Adding this configuration is not enough to make OVS sample drops. The apropriate configuration IPFIX needs to be added to those chassis that you wish to sample from. See man(5) ovs-vswitchd.conf for more details. Signed-off-by: Adrian Moreno --- NEWS | 2 + controller/ovn-controller.c | 44 +++++++++++++++++ controller/physical.c | 44 +++++++++++++---- controller/physical.h | 6 +++ northd/automake.mk | 2 + northd/debug.c | 98 +++++++++++++++++++++++++++++++++++++ northd/debug.h | 30 ++++++++++++ northd/northd.c | 77 ++++++++++++++++------------- northd/ovn-northd.8.xml | 26 ++++++++++ ovn-nb.xml | 28 +++++++++++ ovn-sb.xml | 29 +++++++++++ tests/ovn.at | 67 ++++++++++++++++--------- 12 files changed, 384 insertions(+), 69 deletions(-) create mode 100644 northd/debug.c create mode 100644 northd/debug.h diff --git a/NEWS b/NEWS index 224a7b83e..6c4573b50 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,7 @@ Post v22.09.0 ------------- + - ovn-northd: Add configuration knobs to enable drop sampling using OVS's + per-flow IPFIX sampling. OVN v22.09.0 - 16 Sep 2022 -------------------------- diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 8895c7a2b..686d5fa86 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -3150,6 +3150,8 @@ lflow_output_sb_meter_handler(struct engine_node *node, void *data) struct ed_type_pflow_output { /* Desired physical flows. */ struct ovn_desired_flow_table flow_table; + /* Drop debugging options. */ + struct physical_debug debug; }; static void init_physical_ctx(struct engine_node *node, @@ -3194,6 +3196,12 @@ static void init_physical_ctx(struct engine_node *node, chassis = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id); } + struct sbrec_sb_global_table *sb_global_table = + (struct sbrec_sb_global_table *)EN_OVSDB_GET( + engine_get_input("SB_sb_global", node)); + const struct sbrec_sb_global *sb_global = + sbrec_sb_global_table_first(sb_global_table); + ovs_assert(br_int && chassis); struct ed_type_ct_zones *ct_zones_data = @@ -3215,6 +3223,13 @@ static void init_physical_ctx(struct engine_node *node, p_ctx->local_bindings = &rt_data->lbinding_data.bindings; p_ctx->patch_ofports = &non_vif_data->patch_ofports; p_ctx->chassis_tunnels = &non_vif_data->chassis_tunnels; + p_ctx->debug.collector_set_id = smap_get_uint(&sb_global->options, + "debug_drop_collector_set", + 0); + + p_ctx->debug.obs_domain_id = smap_get_uint(&sb_global->options, + "debug_drop_domain_id", + 0); } static void * @@ -3417,6 +3432,33 @@ pflow_output_activated_ports_handler(struct engine_node *node, void *data) return true; } +static bool +pflow_output_sb_sb_global_handler(struct engine_node *node, void *data) +{ + struct sbrec_sb_global_table *sb_global_table = + (struct sbrec_sb_global_table *)EN_OVSDB_GET( + engine_get_input("SB_sb_global", node)); + const struct sbrec_sb_global *sb_global = + sbrec_sb_global_table_first(sb_global_table); + + struct ed_type_pflow_output *pfo = data; + + uint32_t collector_set_id = smap_get_uint(&sb_global->options, + "debug_drop_collector_set", + 0); + uint32_t obs_domain_id = smap_get_uint(&sb_global->options, + "debug_drop_domain_id", + 0); + + if (pfo->debug.collector_set_id != collector_set_id || + pfo->debug.obs_domain_id != obs_domain_id) { + engine_set_node_state(node, EN_UPDATED); + pfo->debug.collector_set_id = collector_set_id; + pfo->debug.obs_domain_id = obs_domain_id; + } + return true; +} + static void * en_flow_output_init(struct engine_node *node OVS_UNUSED, struct engine_arg *arg OVS_UNUSED) @@ -3759,6 +3801,8 @@ main(int argc, char *argv[]) engine_add_input(&en_pflow_output, &en_mff_ovn_geneve, NULL); engine_add_input(&en_pflow_output, &en_ovs_open_vswitch, NULL); engine_add_input(&en_pflow_output, &en_ovs_bridge, NULL); + engine_add_input(&en_pflow_output, &en_sb_sb_global, + pflow_output_sb_sb_global_handler); engine_add_input(&en_northd_options, &en_sb_sb_global, en_northd_options_sb_sb_global_handler); diff --git a/controller/physical.c b/controller/physical.c index 415d16b76..eb9f01716 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -834,14 +834,32 @@ put_zones_ofpacts(const struct zone_ids *zone_ids, struct ofpbuf *ofpacts_p) } static void -add_default_drop_flow(uint8_t table_id, +put_drop(const struct physical_debug *debug, uint8_t table_id, + struct ofpbuf *ofpacts) +{ + if (debug->collector_set_id) { + struct ofpact_sample *os = ofpact_put_SAMPLE(ofpacts); + os->probability = UINT16_MAX; + os->collector_set_id = debug->collector_set_id; + os->obs_domain_id = (debug->obs_domain_id << 24); + os->obs_point_id = table_id; + } +} + +static void +add_default_drop_flow(const struct physical_ctx *p_ctx, + uint8_t table_id, struct ovn_desired_flow_table *flow_table) { struct match match = MATCH_CATCHALL_INITIALIZER; struct ofpbuf ofpacts; ofpbuf_init(&ofpacts, 0); + + put_drop(&p_ctx->debug, table_id, &ofpacts); ofctrl_add_flow(flow_table, table_id, 0, 0, &match, &ofpacts, hc_uuid); + + ofpbuf_uninit(&ofpacts); } static void @@ -849,6 +867,7 @@ put_local_common_flows(uint32_t dp_key, const struct sbrec_port_binding *pb, const struct sbrec_port_binding *parent_pb, const struct zone_ids *zone_ids, + const struct physical_debug *debug, struct ofpbuf *ofpacts_p, struct ovn_desired_flow_table *flow_table) { @@ -884,6 +903,7 @@ put_local_common_flows(uint32_t dp_key, * and the MLF_ALLOW_LOOPBACK flag is not set. */ match_init_catchall(&match); ofpbuf_clear(ofpacts_p); + put_drop(debug, OFTABLE_CHECK_LOOPBACK, ofpacts_p); match_set_metadata(&match, htonll(dp_key)); match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, 0, MLF_ALLOW_LOOPBACK); @@ -1155,6 +1175,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, const struct hmap *chassis_tunnels, const struct sbrec_port_binding *binding, const struct sbrec_chassis *chassis, + const struct physical_debug *debug, struct ovn_desired_flow_table *flow_table, struct ofpbuf *ofpacts_p) { @@ -1178,7 +1199,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, struct zone_ids binding_zones = get_zone_ids(binding, ct_zones); put_local_common_flows(dp_key, binding, NULL, &binding_zones, - ofpacts_p, flow_table); + debug, ofpacts_p, flow_table); ofpbuf_clear(ofpacts_p); match_outport_dp_and_port_keys(&match, dp_key, port_key); @@ -1354,7 +1375,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, /* Pass the parent port binding if the port is a nested * container. */ put_local_common_flows(dp_key, binding, parent_port, &zone_ids, - ofpacts_p, flow_table); + debug, ofpacts_p, flow_table); /* Table 0, Priority 150 and 100. * ============================== @@ -1486,6 +1507,7 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name, /* Drop LOCAL_ONLY traffic leaking through localnet ports. */ ofpbuf_clear(ofpacts_p); + put_drop(debug, OFTABLE_CHECK_LOOPBACK, ofpacts_p); match_outport_dp_and_port_keys(&match, dp_key, port_key); match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, MLF_LOCAL_ONLY, MLF_LOCAL_ONLY); @@ -1883,7 +1905,8 @@ physical_eval_port_binding(struct physical_ctx *p_ctx, p_ctx->local_bindings, p_ctx->patch_ofports, p_ctx->chassis_tunnels, - pb, p_ctx->chassis, flow_table, &ofpacts); + pb, p_ctx->chassis, &p_ctx->debug, + flow_table, &ofpacts); ofpbuf_uninit(&ofpacts); } @@ -2006,7 +2029,8 @@ physical_run(struct physical_ctx *p_ctx, p_ctx->local_bindings, p_ctx->patch_ofports, p_ctx->chassis_tunnels, binding, - p_ctx->chassis, flow_table, &ofpacts); + p_ctx->chassis, &p_ctx->debug, + flow_table, &ofpacts); } /* Handle output to multicast groups, in tables 37 and 38. */ @@ -2130,7 +2154,7 @@ physical_run(struct physical_ctx *p_ctx, * * Drop packets tha do not match any tunnel in_port. */ - add_default_drop_flow(OFTABLE_PHY_TO_LOG, flow_table); + add_default_drop_flow(p_ctx, OFTABLE_PHY_TO_LOG, flow_table); /* Table 37, priority 150. * ======================= @@ -2182,7 +2206,7 @@ physical_run(struct physical_ctx *p_ctx, * * Drop packets that do not match previous flows. */ - add_default_drop_flow(OFTABLE_LOCAL_OUTPUT, flow_table); + add_default_drop_flow(p_ctx, OFTABLE_LOCAL_OUTPUT, flow_table); /* Table 39, Priority 0. * ======================= @@ -2215,20 +2239,20 @@ physical_run(struct physical_ctx *p_ctx, * * Drop packets that do not match previous flows. */ - add_default_drop_flow(OFTABLE_LOG_TO_PHY, flow_table); + add_default_drop_flow(p_ctx, OFTABLE_LOG_TO_PHY, flow_table); /* Table 68, priority 0. * ====================== * * Drop packets that do not match previous flows. */ - add_default_drop_flow(OFTABLE_CHK_LB_HAIRPIN, flow_table); + add_default_drop_flow(p_ctx, OFTABLE_CHK_LB_HAIRPIN, flow_table); /* Table 70, priority 0. * ====================== * * Drop packets that do not match previous flows. */ - add_default_drop_flow(OFTABLE_CT_SNAT_HAIRPIN, flow_table); + add_default_drop_flow(p_ctx, OFTABLE_CT_SNAT_HAIRPIN, flow_table); ofpbuf_uninit(&ofpacts); } diff --git a/controller/physical.h b/controller/physical.h index 1b8f1ea55..f450dca94 100644 --- a/controller/physical.h +++ b/controller/physical.h @@ -43,6 +43,11 @@ struct local_nonvif_data; #define OVN_GENEVE_TYPE 0x80 /* Critical option. */ #define OVN_GENEVE_LEN 4 +struct physical_debug { + uint32_t collector_set_id; + uint32_t obs_domain_id; +}; + struct physical_ctx { struct ovsdb_idl_index *sbrec_port_binding_by_name; struct ovsdb_idl_index *sbrec_port_binding_by_datapath; @@ -59,6 +64,7 @@ struct physical_ctx { struct shash *local_bindings; struct simap *patch_ofports; struct hmap *chassis_tunnels; + struct physical_debug debug; }; void physical_register_ovs_idl(struct ovsdb_idl *); diff --git a/northd/automake.mk b/northd/automake.mk index 81582867d..14cf525d8 100644 --- a/northd/automake.mk +++ b/northd/automake.mk @@ -1,6 +1,8 @@ # ovn-northd bin_PROGRAMS += northd/ovn-northd northd_ovn_northd_SOURCES = \ + northd/debug.c \ + northd/debug.h \ northd/mac-binding-aging.c \ northd/mac-binding-aging.h \ northd/northd.c \ diff --git a/northd/debug.c b/northd/debug.c new file mode 100644 index 000000000..59da5d4f6 --- /dev/null +++ b/northd/debug.c @@ -0,0 +1,98 @@ +#include + +#include + +#include "debug.h" + +#include "openvswitch/dynamic-string.h" +#include "openvswitch/vlog.h" +#include "smap.h" + +VLOG_DEFINE_THIS_MODULE(debug) + +struct debug_config { + bool enabled; + uint32_t collector_set_id; + uint32_t observation_domain_id; + struct ds drop_action; +}; + +static struct debug_config config; + +static bool +debug_enabled(void) +{ + return config.collector_set_id != 0; +} + +void +init_debug_config(const struct nbrec_nb_global *nb) +{ + + const struct smap *options = &nb->options; + uint32_t collector_set_id = smap_get_uint(options, + "debug_drop_collector_set", + 0); + uint32_t observation_domain_id = smap_get_uint(options, + "debug_drop_domain_id", + 0); + + if (collector_set_id != config.collector_set_id || + observation_domain_id != config.observation_domain_id || + !config.drop_action.length) { + + if (observation_domain_id >= UINT8_MAX) { + VLOG_ERR("Observation domain id must be an 8-bit number"); + return; + } + + config.collector_set_id = collector_set_id; + config.observation_domain_id = observation_domain_id; + + ds_clear(&config.drop_action); + + if (debug_enabled()) { + ds_put_format(&config.drop_action, + "sample(probability=65535," + "collector_set=%d," + "obs_domain=%d," + "obs_point=$cookie); ", + config.collector_set_id, + config.observation_domain_id); + + ds_put_cstr(&config.drop_action, "/* drop */"); + VLOG_DBG("Debug drop sampling: enabled"); + } else { + ds_put_cstr(&config.drop_action, "drop;"); + VLOG_DBG("Debug drop sampling: disabled"); + } + } +} + +void +destroy_debug_config(void) +{ + if (config.drop_action.string) { + ds_destroy(&config.drop_action); + ds_init(&config.drop_action); + } +} + +const char * +debug_drop_action(void) { + if (OVS_UNLIKELY(debug_enabled())) { + return ds_cstr_ro(&config.drop_action); + } else { + return "drop;"; + } +} + +const char * +debug_implicit_drop_action(void) +{ + if (OVS_UNLIKELY(debug_enabled())) { + return ds_cstr_ro(&config.drop_action); + } else { + return "/* drop */"; + } +} diff --git a/northd/debug.h b/northd/debug.h new file mode 100644 index 000000000..c1a5e5aad --- /dev/null +++ b/northd/debug.h @@ -0,0 +1,30 @@ +/* + * 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 NORTHD_DEBUG_H +#define NORTHD_DEBUG_H 1 + +#include +#include + +#include "lib/ovn-nb-idl.h" +#include "openvswitch/dynamic-string.h" + +void init_debug_config(const struct nbrec_nb_global *nb); +void destroy_debug_config(void); + +const char *debug_drop_action(void); +const char *debug_implicit_drop_action(void); + +#endif /* NORTHD_DEBUG_H */ diff --git a/northd/northd.c b/northd/northd.c index 4b1829d37..b45f19689 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -17,6 +17,7 @@ #include #include +#include "debug.h" #include "bitmap.h" #include "dirs.h" #include "ipam.h" @@ -3827,7 +3828,7 @@ build_lb_vip_actions(struct ovn_lb_vip *lb_vip, if (!n_active_backends) { if (!lb_vip->empty_backend_rej) { ds_clear(action); - ds_put_cstr(action, "drop;"); + ds_put_cstr(action, debug_drop_action()); skip_hash_fields = true; } else { reject = true; @@ -5161,7 +5162,7 @@ __ovn_lflow_add_default_drop(struct hmap *lflow_map, enum ovn_stage stage, const char *where) { - ovn_lflow_add_at(lflow_map, od, stage, 0, "1", "drop;", + ovn_lflow_add_at(lflow_map, od, stage, 0, "1", debug_drop_action(), NULL, NULL, NULL, where ); } @@ -6392,7 +6393,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, } else { ds_put_format(match, " && (%s)", acl->match); build_acl_log(actions, acl, meter_groups); - ds_put_cstr(actions, "/* drop */"); + ds_put_cstr(actions, debug_implicit_drop_action()); ovn_lflow_add_with_hint(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET, ds_cstr(match), ds_cstr(actions), @@ -6420,7 +6421,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, } else { ds_put_format(match, " && (%s)", acl->match); build_acl_log(actions, acl, meter_groups); - ds_put_cstr(actions, "/* drop */"); + ds_put_cstr(actions, debug_implicit_drop_action()); ovn_lflow_add_with_hint(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET, ds_cstr(match), ds_cstr(actions), @@ -6437,7 +6438,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, actions, &acl->header_, meter_groups); } else { build_acl_log(actions, acl, meter_groups); - ds_put_cstr(actions, "/* drop */"); + ds_put_cstr(actions, debug_implicit_drop_action()); ovn_lflow_add_with_hint(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET, acl->match, ds_cstr(actions), @@ -6673,9 +6674,9 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, use_ct_inv_match ? "ct.inv || " : "", ct_blocked_match); ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX - 3, - ds_cstr(&match), "drop;"); + ds_cstr(&match), debug_drop_action()); ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3, - ds_cstr(&match), "drop;"); + ds_cstr(&match), debug_drop_action()); /* Ingress and Egress ACL Table (Priority 65535 - 3). * @@ -7774,7 +7775,7 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, rp->lsp_addrs[k].ipv4_addrs[l].addr_s); ovn_lflow_add_with_lport_and_hint( lflows, op->od, S_SWITCH_IN_EXTERNAL_PORT, 100, - ds_cstr(&match), "drop;", port->key, + ds_cstr(&match), debug_drop_action(), port->key, &op->nbsp->header_); } for (size_t l = 0; l < rp->lsp_addrs[k].n_ipv6_addrs; l++) { @@ -7790,7 +7791,7 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, rp->lsp_addrs[k].ipv6_addrs[l].addr_s); ovn_lflow_add_with_lport_and_hint( lflows, op->od, S_SWITCH_IN_EXTERNAL_PORT, 100, - ds_cstr(&match), "drop;", port->key, + ds_cstr(&match), debug_drop_action(), port->key, &op->nbsp->header_); } @@ -7805,7 +7806,8 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, ovn_lflow_add_with_lport_and_hint(lflows, op->od, S_SWITCH_IN_EXTERNAL_PORT, 100, ds_cstr(&match), - "drop;", port->key, + debug_drop_action(), + port->key, &op->nbsp->header_); } } @@ -7843,7 +7845,7 @@ build_lswitch_flows(const struct hmap *datapaths, "outport = \""MC_UNKNOWN "\"; output;"); } else { ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_UNKNOWN, 50, - "outport == \"none\"", "drop;"); + "outport == \"none\"", debug_drop_action()); } ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_UNKNOWN, 0, "1", "output;"); @@ -7886,18 +7888,18 @@ build_lswitch_lflows_admission_control(struct ovn_datapath *od, if (!is_vlan_transparent(od)) { /* Block logical VLANs. */ ovn_lflow_add(lflows, od, S_SWITCH_IN_CHECK_PORT_SEC, 100, - "vlan.present", "drop;"); + "vlan.present", debug_drop_action()); } /* Broadcast/multicast source address is invalid. */ ovn_lflow_add(lflows, od, S_SWITCH_IN_CHECK_PORT_SEC, 100, - "eth.src[40]", "drop;"); + "eth.src[40]", debug_drop_action()); ovn_lflow_add(lflows, od, S_SWITCH_IN_CHECK_PORT_SEC, 50, "1", REGBIT_PORT_SEC_DROP" = check_in_port_sec(); next;"); ovn_lflow_add(lflows, od, S_SWITCH_IN_APPLY_PORT_SEC, 50, - REGBIT_PORT_SEC_DROP" == 1", "drop;"); + REGBIT_PORT_SEC_DROP" == 1", debug_drop_action()); ovn_lflow_add(lflows, od, S_SWITCH_IN_APPLY_PORT_SEC, 0, "1", "next;"); } @@ -8426,7 +8428,7 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, */ if (!mcast_sw_info->flood_relay && !mcast_sw_info->flood_static) { - ds_put_cstr(actions, "drop;"); + ds_put_cstr(actions, debug_drop_action()); } ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 80, @@ -8951,7 +8953,7 @@ build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od, out_port->json_key); } else if (!strcmp(rule->action, "drop")) { - ds_put_cstr(&actions, "drop;"); + ds_put_cstr(&actions, debug_drop_action()); } else if (!strcmp(rule->action, "allow")) { uint32_t pkt_mark = ovn_smap_get_uint(&rule->options, "pkt_mark", 0); if (pkt_mark) { @@ -9801,7 +9803,7 @@ add_route(struct hmap *lflows, struct ovn_datapath *od, struct ds common_actions = DS_EMPTY_INITIALIZER; struct ds actions = DS_EMPTY_INITIALIZER; if (is_discard_route) { - ds_put_format(&actions, "drop;"); + ds_put_cstr(&actions, debug_drop_action()); } else { ds_put_format(&common_actions, REG_ECMP_GROUP_ID" = 0; %s = ", is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6); @@ -10584,7 +10586,7 @@ build_lrouter_arp_flow(struct ovn_datapath *od, struct ovn_port *op, ds_put_format(&match, " && %s", ds_cstr(extra_match)); } if (drop) { - ds_put_format(&actions, "drop;"); + ds_put_cstr(&actions, debug_drop_action()); } else { ds_put_format(&actions, "eth.dst = eth.src; " @@ -10640,7 +10642,7 @@ build_lrouter_nd_flow(struct ovn_datapath *od, struct ovn_port *op, } if (drop) { - ds_put_format(&actions, "drop;"); + ds_put_cstr(&actions, debug_drop_action()); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_IP_INPUT, priority, ds_cstr(&match), ds_cstr(&actions), hint); } else { @@ -10790,7 +10792,7 @@ build_lrouter_drop_own_dest(struct ovn_port *op, enum ovn_stage stage, char *match = xasprintf("ip4.dst == {%s}", ds_cstr(&match_ips)); ovn_lflow_add_with_hint(lflows, op->od, stage, priority, - match, "drop;", + match, debug_drop_action(), &op->nbrp->header_); free(match); } @@ -10819,7 +10821,7 @@ build_lrouter_drop_own_dest(struct ovn_port *op, enum ovn_stage stage, char *match = xasprintf("ip6.dst == {%s}", ds_cstr(&match_ips)); ovn_lflow_add_with_hint(lflows, op->od, stage, priority, - match, "drop;", + match, debug_drop_action(), &op->nbrp->header_); free(match); } @@ -10987,7 +10989,7 @@ build_adm_ctrl_flows_for_lrouter( /* Logical VLANs not supported. * Broadcast/multicast source address is invalid. */ ovn_lflow_add(lflows, od, S_ROUTER_IN_ADMISSION, 100, - "vlan.present || eth.src[40]", "drop;"); + "vlan.present || eth.src[40]", debug_drop_action()); /* Default action for L2 security is to drop. */ ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_ADMISSION); @@ -11580,7 +11582,7 @@ build_mcast_lookup_flows_for_lrouter( * i.e., router solicitation and router advertisement. */ ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING, 10550, - "nd_rs || nd_ra", "drop;"); + "nd_rs || nd_ra", debug_drop_action()); if (!od->mcast_info.rtr.relay) { return; } @@ -11627,13 +11629,13 @@ build_mcast_lookup_flows_for_lrouter( ds_put_format(match, "eth.src == %s && igmp", op->lrp_networks.ea_s); ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING, 10550, - ds_cstr(match), "drop;"); + ds_cstr(match), debug_drop_action()); ds_clear(match); ds_put_format(match, "eth.src == %s && (mldv1 || mldv2)", op->lrp_networks.ea_s); ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING, 10550, - ds_cstr(match), "drop;"); + ds_cstr(match), debug_drop_action()); } ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING, 10460, @@ -11657,7 +11659,7 @@ build_mcast_lookup_flows_for_lrouter( "};"); } else { ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING, 10450, - "ip4.mcast || ip6.mcast", "drop;"); + "ip4.mcast || ip6.mcast", debug_drop_action()); } } } @@ -12483,7 +12485,7 @@ build_misc_local_traffic_drop_flows_for_lrouter( "ip4.dst == 127.0.0.0/8 || " "ip4.src == 0.0.0.0/8 || " "ip4.dst == 0.0.0.0/8", - "drop;"); + debug_drop_action()); /* Drop ARP packets (priority 85). ARP request packets for router's own * IPs are handled with priority-90 flows. @@ -12491,7 +12493,7 @@ build_misc_local_traffic_drop_flows_for_lrouter( * IPs are handled with priority-90 flows. */ ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 85, - "arp || nd", "drop;"); + "arp || nd", debug_drop_action()); /* Allow IPv6 multicast traffic that's supposed to reach the * router pipeline (e.g., router solicitations). @@ -12501,21 +12503,22 @@ build_misc_local_traffic_drop_flows_for_lrouter( /* Drop other reserved multicast. */ ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 83, - "ip6.mcast_rsvd", "drop;"); + "ip6.mcast_rsvd", debug_drop_action()); /* Allow other multicast if relay enabled (priority 82). */ ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 82, "ip4.mcast || ip6.mcast", - od->mcast_info.rtr.relay ? "next;" : "drop;"); + (od->mcast_info.rtr.relay ? "next;" : + debug_drop_action())); /* Drop Ethernet local broadcast. By definition this traffic should * not be forwarded.*/ ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 50, - "eth.bcast", "drop;"); + "eth.bcast", debug_drop_action()); /* TTL discard */ ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 30, - "ip4 && ip.ttl == {0, 1}", "drop;"); + "ip4 && ip.ttl == {0, 1}", debug_drop_action()); /* Pass other traffic not already handled to the next table for * routing. */ @@ -12777,7 +12780,7 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, op_put_v4_networks(match, op, true); ds_put_cstr(match, " && "REGBIT_EGRESS_LOOPBACK" == 0"); ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 100, - ds_cstr(match), "drop;", + ds_cstr(match), debug_drop_action(), &op->nbrp->header_); /* ICMP echo reply. These flows reply to ICMP echo requests @@ -13834,8 +13837,8 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, struct ovn_port *op = ovn_port_find(ports, nat->logical_port); if (op && op->nbsp && !strcmp(op->nbsp->type, "virtual")) { ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT, - 80, ds_cstr(match), "drop;", - &nat->header_); + 80, ds_cstr(match), + debug_drop_action(), &nat->header_); } ds_put_format(match, " && is_chassis_resident(\"%s\")", nat->logical_port); @@ -15565,6 +15568,7 @@ northd_destroy(struct northd_data *data) destroy_datapaths_and_ports(&data->datapaths, &data->ports, &data->lr_list); + destroy_debug_config(); } static void @@ -15648,6 +15652,9 @@ ovnnb_db_run(struct northd_input *input_data, false); build_chassis_features(input_data, &data->features); + + init_debug_config(nb); + build_datapaths(input_data, ovnsb_txn, &data->datapaths, &data->lr_list); build_lbs(input_data, &data->datapaths, &data->lbs, &data->lb_groups); build_ports(input_data, ovnsb_txn, sbrec_chassis_by_name, diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index cb996279f..68a01829c 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -4847,4 +4847,30 @@ clone {

    +

    Drop sampling

    + +

    + As described in the previous section, there are several places where + ovn-northd might decided to drop a packet by explicitly creating a + Logical_Flow with the drop; action. +

    + +

    + When debug drop-sampling has been cofigured in the OVN Northbound + database, the ovn-northd will replace all the drop; + actions with a sample(priority=65535, collector_set=id, + obs_domain=obs_id, obs_point=@cookie) action, where: +

      +
    • + id is the value the debug_drop_collector_set + option configured in the OVN Northbound. +
    • +
    • + obs_id has it's 8 most significant bits equal to the value + of the debug_drop_domain_id option in the OVN Northbound + and it's 24 least significant bits equal to the datapath's tunnel key. +
    • +
    +

    + diff --git a/ovn-nb.xml b/ovn-nb.xml index f41e9d7c0..548e2ddb0 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -264,6 +264,34 @@

    + +

    + If set to a 8-bit number and if + debug_drop_collector_set is also configured, + ovn-northd will add a sample action to + every logical flow that contains a 'drop' action. + The 8 most significant bits of the observation_domain_id field will + be those specified in the + debug_drop_domain_id. + The 24 least significant bits of the observation_domain_id field will + be the datapath's key. +

    +

    + The observation_point_id will be set to the first 32 bits of the + logical flow's UUID. +

    +
    + + +

    + If set to a 32-bit number ovn-northd will add a + sample action to every logical flow that contains a + 'drop' action. The sample action will have the specified + collector_set_id. The value must match that of the local OVS + configuration as described in ovs-actions(7). +

    +
    +

    These options control how routes are advertised between OVN diff --git a/ovn-sb.xml b/ovn-sb.xml index a09891d10..60d623093 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -198,6 +198,35 @@ BFD option mult value to use when configuring BFD on tunnel interfaces. + + +

    + If set to a 8-bit number and if + debug_drop_collector_set is also configured, + ovn-controller will add a sample action + to every flow that does not come from a logical flow that contains + a 'drop' action. + The 8 most significant bits of the observation_domain_id field will + be those specified in the + debug_drop_domain_id. + The 24 least significant bits of the observation_domain_id field + will be zero. +

    +

    + The observation_point_id will be set to the OpenFlow table number. +

    + + + +

    + If set to a 32-bit number ovn-controller will add a + sample action to every flow that does not come from + a logical flow that contains a 'drop' action. + The sample action will have the specified collector_set_id. + The value must match that of the local OVS configuration as + described in ovs-actions(7). +

    +
    diff --git a/tests/ovn.at b/tests/ovn.at index 0a6489ea0..caafee89a 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -33055,6 +33055,43 @@ check_default_flows() { done } +# Check that every drop flow gets sampled. +check_sample_drops() { + + check ovn-nbctl -- remove NB_Global . options debug_drop_collector_set \ + -- remove NB_Global . options debug_drop_domain_id + check ovn-nbctl --wait=hv sync + + ovs-ofctl dump-flows --no-stats br-int > oflows_nosample + AT_CAPTURE_FILE([oflows_nosample]) + # Take match part of flows that contain "drop". + drop_matches="$(grep 'drop' oflows_nosample | grep -oP 'table=\d*, priority=.* ')" + + check ovn-nbctl -- set NB_Global . options:debug_drop_collector_set="123" \ + -- set NB_Global . options:debug_drop_domain_id="1" + check ovn-nbctl --wait=hv sync + + ovs-ofctl dump-flows --no-stats br-int > oflows_sample + AT_CAPTURE_FILE([oflows_sample]) + + # Check that every drop has now contains a "sample" action. + for flow in "$drop_matches"; do + AT_CHECK([grep -q "$flow actions=.*sample.*" oflows_sample], [0], [ignore], [ignore], [echo "Flow $flow has a drop and did not get sampled"]) + done +} + +check_drops() { + as hv1 + check_default_flows + as hv2 + check_default_flows + + as hv1 + check_sample_drops + as hv2 + check_sample_drops +} + # Logical network: # Two LRs - R1 and R2 that are connected to each other as peers in 20.0.0.0/24 # network. R1 has a switchs ls1 (191.168.1.0/24) connected to it. @@ -33120,10 +33157,7 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \ wait_for_ports_up check ovn-nbctl --wait=hv sync -as hv1 -check_default_flows -as hv2 -check_default_flows +check_debug # Add stateless ACL check ovn-nbctl --wait=sb \ @@ -33131,10 +33165,7 @@ check ovn-nbctl --wait=sb \ check ovn-nbctl --wait=sb \ -- acl-add ls2 from-lport 100 'ip4' allow-stateless -as hv1 -check_default_flows -as hv2 -check_default_flows +check_debug check ovn-nbctl --wait=sb acl-del ls1 check ovn-nbctl --wait=sb acl-del ls2 @@ -33145,10 +33176,7 @@ check ovn-nbctl --wait=sb \ check ovn-nbctl --wait=sb \ -- acl-add ls2 from-lport 100 "udp" allow-related -as hv1 -check_default_flows -as hv2 -check_default_flows +check_debug check ovn-nbctl --wait=sb acl-del ls1 check ovn-nbctl --wait=sb acl-del ls2 @@ -33162,10 +33190,7 @@ check ovn-nbctl --wait=sb \ -- lb-add lb2 "10.0.1.1" "10.0.1.2" \ -- ls-lb-add ls2 lb2 -as hv1 -check_default_flows -as hv2 -check_default_flows +check_drops # LB + stateless ACL check ovn-nbctl --wait=sb \ @@ -33173,10 +33198,7 @@ check ovn-nbctl --wait=sb \ check ovn-nbctl --wait=sb \ -- acl-add ls2 from-lport 100 'ip4' allow-stateless -as hv1 -check_default_flows -as hv2 -check_default_flows +check_drops check ovn-nbctl --wait=sb acl-del ls1 check ovn-nbctl --wait=sb acl-del ls2 @@ -33187,10 +33209,7 @@ check ovn-nbctl --wait=sb \ check ovn-nbctl --wait=sb \ -- acl-add ls2 from-lport 100 "udp" allow-related -as hv1 -check_default_flows -as hv2 -check_default_flows +check_drops OVN_CLEANUP([hv1],[hv2]) AT_CLEANUP