From patchwork Tue Sep 26 10:03:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Musil X-Patchwork-Id: 1839584 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=UbhRAHjR; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RvwLt6gZ3z1ynX for ; Tue, 26 Sep 2023 20:04:05 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 532F7417C1; Tue, 26 Sep 2023 10:04:03 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 532F7417C1 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=UbhRAHjR 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 aanS5F9eVG7O; Tue, 26 Sep 2023 10:04:02 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id EDDE240A1E; Tue, 26 Sep 2023 10:04:00 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org EDDE240A1E Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id AD40DC0071; Tue, 26 Sep 2023 10:04:00 +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 1D299C0032 for ; Tue, 26 Sep 2023 10:03:59 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id DEECF40AF4 for ; Tue, 26 Sep 2023 10:03:58 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org DEECF40AF4 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 pbCAYH4FcIwx for ; Tue, 26 Sep 2023 10:03:57 +0000 (UTC) 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 94C8840A1E for ; Tue, 26 Sep 2023 10:03:57 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 94C8840A1E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1695722636; 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=7XwVlL/86ne8+c8ERF+zbJYwy468qJMS8xjVgPz/+60=; b=UbhRAHjR/W0VvszmLNey4xC/rXF3brjg8/xCDUvuyi6/F5V2Nle1KbQJKuKfNzj4uam4fK n6ywKBVQlzHm8BtxaxoQXN4HHrxDpSeMwo2HmHVrTdganqfGRZnLho279GCOJh833mLs1W vPZA3pO8tNI9Q9JMmP5Vr688QV5OToY= 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-274-oLjo5kJVN5C4VBcF7LfWgA-1; Tue, 26 Sep 2023 06:03:55 -0400 X-MC-Unique: oLjo5kJVN5C4VBcF7LfWgA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B123885A5A8; Tue, 26 Sep 2023 10:03:54 +0000 (UTC) Received: from amusil.redhat.com (unknown [10.45.224.62]) by smtp.corp.redhat.com (Postfix) with ESMTP id 005541055466; Tue, 26 Sep 2023 10:03:53 +0000 (UTC) From: Ales Musil To: dev@openvswitch.org Date: Tue, 26 Sep 2023 12:03:50 +0200 Message-ID: <20230926100352.136273-2-amusil@redhat.com> In-Reply-To: <20230926100352.136273-1-amusil@redhat.com> References: <20230926100352.136273-1-amusil@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: i.maximets@ovn.org Subject: [ovs-dev] [PATCH v2 1/3] ovs-vsctl: Add limit to CT zone X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Add limit to the CT zone DB table with ovs-vsctl helper methods. The limit has two special values besides any number, 0 is unlimited and empty limit is to leave the value untouched in the datapath. This is preparation step and the value is not yet propagated to the datapath. Signed-off-by: Ales Musil Acked-by: Simon Horman --- NEWS | 2 + tests/ovs-vsctl.at | 58 ++++++++++++++++++++ utilities/ovs-vsctl.8.in | 20 ++++++- utilities/ovs-vsctl.c | 108 ++++++++++++++++++++++++++++++++++++- vswitchd/vswitch.ovsschema | 9 +++- vswitchd/vswitch.xml | 5 ++ 6 files changed, 198 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 6b45492f1..e86e7f364 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ Post-v3.2.0 from older version is supported but it may trigger more leader elections during the process, and error logs complaining unrecognized fields may be observed on old nodes. + - CT: + * Add support for setting CT zone limit via DB. v3.2.0 - 17 Aug 2023 diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at index a368bff6e..b033eaf1f 100644 --- a/tests/ovs-vsctl.at +++ b/tests/ovs-vsctl.at @@ -975,6 +975,47 @@ AT_CHECK( [0], [stdout]) AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:10, Timeout Policies: system default ]) +AT_CHECK([RUN_OVS_VSCTL([del-zone-tp netdev zone=10])]) + +AT_CHECK([RUN_OVS_VSCTL([list-zone-limit netdev])]) + +AT_CHECK([RUN_OVS_VSCTL([add-zone-limit netdev zone=1 limit=1])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-limit netdev])], [0], [dnl +Zone: 1, Limit: 1 +]) + +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-zone-limit netdev zone=1 limit=5])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-limit netdev])], [0], [dnl +Zone: 1, Limit: 5 +]) + +AT_CHECK([RUN_OVS_VSCTL([del-zone-limit netdev zone=1])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-limit netdev])]) + +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-zone-limit netdev zone=10 limit=5])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-limit netdev])], [0], [dnl +Zone: 10, Limit: 5 +]) + +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-zone-tp netdev zone=10 icmp_first=1 icmp_reply=2])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [dnl +Zone:10, Timeout Policies: icmp_first=1 icmp_reply=2 +]) + +AT_CHECK([RUN_OVS_VSCTL([del-zone-limit netdev zone=10])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-limit netdev])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [dnl +Zone:10, Timeout Policies: icmp_first=1 icmp_reply=2 +]) + +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-zone-limit netdev zone=10 limit=5])]) +AT_CHECK([RUN_OVS_VSCTL([del-zone-tp netdev zone=10])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-limit netdev])], [0], [dnl +Zone: 10, Limit: 5 +]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [dnl +Zone:10, Timeout Policies: system default +]) AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 'capabilities={recirc=true}' -- set Open_vSwitch . datapaths:"system"=@m])], [0], [stdout]) AT_CHECK([RUN_OVS_VSCTL([list-dp-cap system])], [0], [recirc=true @@ -1123,6 +1164,23 @@ AT_CHECK([RUN_OVS_VSCTL([del-zone-tp netdev zone=11])], AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:2, Timeout Policies: icmp_first=2 icmp_reply=3 ]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-limit netdevxx zone=5 limit=1])], + [1], [], [ovs-vsctl: datapath netdevxx does not exist +]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-limit netdev zone=88888 limit=1])], + [1], [], [ovs-vsctl: zone_id (88888) out of range +]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-limit netdev zone=5 limit=-1])], + [1], [], [ovs-vsctl: limit (-1) out of range +]) +AT_CHECK([RUN_OVS_VSCTL([del-zone-limit netdev zone=10])], + [1], [], [ovs-vsctl: zone_id 10 does not exist +]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-limit netdev zone=5 limit=1])]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-limit netdev zone=5 limit=2])], + [1], [], [ovs-vsctl: zone_id 5 already exists +]) + AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 'capabilities={recirc=true}' -- set Open_vSwitch . datapaths:"system"=@m])], [0], [stdout]) AT_CHECK([RUN_OVS_VSCTL([list-dp-cap nosystem])], [1], [], [ovs-vsctl: datapath "nosystem" record not found diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in index 9e319aa1c..e6c0d6b2c 100644 --- a/utilities/ovs-vsctl.8.in +++ b/utilities/ovs-vsctl.8.in @@ -354,7 +354,7 @@ Prints the name of the bridge that contains \fIiface\fR on standard output. . .SS "Conntrack Zone Commands" -These commands query and modify datapath CT zones and Timeout Policies. +These commands query and modify datapath CT zones, Timeout Policies and Limits. . .IP "[\fB\-\-may\-exist\fR] \fBadd\-zone\-tp \fIdatapath \fBzone=\fIzone_id \fIpolicies\fR" Creates a conntrack zone timeout policy with \fIzone_id\fR in @@ -379,6 +379,24 @@ delete a zone that does not exist has no effect. .IP "\fBlist\-zone\-tp \fIdatapath\fR" Prints the timeout policies of all zones in \fIdatapath\fR. . +.IP "[\fB\-\-may\-exist\fR] \fBadd\-zone\-limit \fIdatapath \fBzone=\fIzone_id \fBlimit=\fIzone_limit" +Sets a conntrack zone limit with \fIzone_id\fR in +\fIdatapath\fR. The \fIlimit\fR with value \fB0\fR means unlimited. +.IP +Without \fB\-\-may\-exist\fR, attempting to add a \fIzone_id\fR that +already exists is an error. With \fB\-\-may\-exist\fR, +this command updates the \fIlimit\fR if \fIzone_id\fR already exists. +. +.IP "[\fB\-\-if\-exists\fR] \fBdel\-zone\-imit \fIdatapath \fBzone=\fIzone_id\fR" +Delete the limit associated with \fIzone_id\fR from \fIdatapath\fR. +.IP +Without \fB\-\-if\-exists\fR, attempting to delete a zone that +does not exist is an error. With \fB\-\-if\-exists\fR, attempting to +delete a zone that does not exist has no effect. +. +.IP "\fBlist\-zone\-limit \fIdatapath\fR" +Prints the limits of all zones in \fIdatapath\fR. +. .SS "Datapath Capabilities Command" The command query datapath capabilities. . diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index 5e549df00..e6b51459f 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -1336,7 +1336,16 @@ cmd_del_zone_tp(struct ctl_context *ctx) ctl_fatal("zone id %"PRIu64" does not exist", zone_id); } - if (zone) { + if (!zone) { + return; + } + + if (zone->limit) { + if (zone->timeout_policy) { + ovsrec_ct_timeout_policy_delete(zone->timeout_policy); + } + ovsrec_ct_zone_set_timeout_policy(zone, NULL); + } else { ovsrec_datapath_update_ct_zones_delkey(dp, zone_id); } } @@ -1371,12 +1380,101 @@ cmd_list_zone_tp(struct ctl_context *ctx) } } +static void +cmd_add_zone_limit(struct ctl_context *ctx) +{ + struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx); + int64_t zone_id = -1; + int64_t limit = -1; + + const char *dp_name = ctx->argv[1]; + bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL; + ovs_scan(ctx->argv[2], "zone=%"SCNi64, &zone_id); + ovs_scan(ctx->argv[3], "limit=%"SCNi64, &limit); + + if (zone_id < 0 || zone_id > UINT16_MAX) { + ctl_fatal("zone_id (%"PRIi64") out of range", zone_id); + } + + if (limit < 0 || limit > UINT32_MAX) { + ctl_fatal("limit (%"PRIi64") out of range", limit); + } + + struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, dp_name); + if (!dp) { + ctl_fatal("datapath %s does not exist", dp_name); + } + + struct ovsrec_ct_zone *zone = find_ct_zone(dp, zone_id); + if (zone && !may_exist) { + ctl_fatal("zone_id %"PRIi64" already exists", zone_id); + } + + if (!zone) { + zone = ovsrec_ct_zone_insert(ctx->txn); + ovsrec_datapath_update_ct_zones_setkey(dp, zone_id, zone); + } + + ovsrec_ct_zone_set_limit(zone, &limit, 1); +} + +static void +cmd_del_zone_limit(struct ctl_context *ctx) +{ + struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx); + int64_t zone_id; + + bool must_exist = !shash_find(&ctx->options, "--if-exists"); + const char *dp_name = ctx->argv[1]; + ovs_scan(ctx->argv[2], "zone=%"SCNi64, &zone_id); + + struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, dp_name); + if (!dp) { + ctl_fatal("datapath %s does not exist", dp_name); + } + + struct ovsrec_ct_zone *zone = find_ct_zone(dp, zone_id); + if (must_exist && !zone) { + ctl_fatal("zone_id %"PRIi64" does not exist", zone_id); + } + + if (!zone) { + return; + } + + if (zone->timeout_policy) { + ovsrec_ct_zone_set_limit(zone, NULL, 0); + } else { + ovsrec_datapath_update_ct_zones_delkey(dp, zone_id); + } +} + +static void +cmd_list_zone_limit(struct ctl_context *ctx) +{ + struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx); + + struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, ctx->argv[1]); + if (!dp) { + ctl_fatal("datapath: %s record not found", ctx->argv[1]); + } + + for (int i = 0; i < dp->n_ct_zones; i++) { + struct ovsrec_ct_zone *zone = dp->value_ct_zones[i]; + if (zone->limit) { + ds_put_format(&ctx->output, "Zone: %"PRIu64", Limit: %"PRIu64"\n", + dp->key_ct_zones[i], *zone->limit); + } + } +} + static void pre_get_zone(struct ctl_context *ctx) { ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_datapaths); ovsdb_idl_add_column(ctx->idl, &ovsrec_datapath_col_ct_zones); ovsdb_idl_add_column(ctx->idl, &ovsrec_ct_zone_col_timeout_policy); + ovsdb_idl_add_column(ctx->idl, &ovsrec_ct_zone_col_limit); ovsdb_idl_add_column(ctx->idl, &ovsrec_ct_timeout_policy_col_timeouts); } @@ -3159,6 +3257,14 @@ static const struct ctl_command_syntax vsctl_commands[] = { /* Datapath capabilities. */ {"list-dp-cap", 1, 1, "", pre_get_dp_cap, cmd_list_dp_cap, NULL, "", RO}, + /* CT zone limit. */ + {"add-zone-limit", 3, 3, "", pre_get_zone, cmd_add_zone_limit, NULL, + "--may-exist", RW}, + {"del-zone-limit", 2, 2, "", pre_get_zone, cmd_del_zone_limit, NULL, + "--if-exists", RW}, + {"list-zone-limit", 1, 1, "", pre_get_zone, cmd_list_zone_limit, NULL, + "", RO}, + {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO}, }; diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 2d395ff95..ed90c57d0 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", - "version": "8.4.0", - "cksum": "2738838700 27127", + "version": "8.5.0", + "cksum": "2723382443 27334", "tables": { "Open_vSwitch": { "columns": { @@ -679,6 +679,11 @@ "type": {"key": {"type": "uuid", "refTable": "CT_Timeout_Policy"}, "min": 0, "max": 1}}, + "limit": { + "type": { "key": {"type": "integer", + "minInteger": 0, + "maxInteger": 4294967295}, + "min": 0, "max": 1}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}}, diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index cfcde34ff..d1674170a 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -6428,6 +6428,11 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \ Connection tracking zone configuration + + Connection tracking limit for this zone. If the limit is unspecified + the datapath configuration is left intact. The value 0 means unlimited. + + Connection tracking timeout policy for this zone. If a timeout policy is not specified, it defaults to the timeout policy in the system. From patchwork Tue Sep 26 10:03:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Musil X-Patchwork-Id: 1839586 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=AKntjZPv; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RvwM04YZ6z1ynX for ; Tue, 26 Sep 2023 20:04:12 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 340D161449; Tue, 26 Sep 2023 10:04:10 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 340D161449 Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=AKntjZPv 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 jkVMhVQcGkzg; Tue, 26 Sep 2023 10:04:08 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id 0F42D61416; Tue, 26 Sep 2023 10:04:07 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 0F42D61416 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 2CE06C0DE4; Tue, 26 Sep 2023 10:04:03 +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 BAA46C0DD9 for ; Tue, 26 Sep 2023 10:04:01 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 9E44E416D4 for ; Tue, 26 Sep 2023 10:04:01 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 9E44E416D4 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=AKntjZPv 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 U539P6VaocD2 for ; Tue, 26 Sep 2023 10:04:00 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp4.osuosl.org (Postfix) with ESMTPS id 360154138D for ; Tue, 26 Sep 2023 10:04:00 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 360154138D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1695722639; 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=9mti0+cQgLTbWDsYeocCo1V2NehbRYuxnV1VzN09clA=; b=AKntjZPvO7IUelOFhQ62jnpGIeBjILl8wYnWnpsWn3bxIItso5hFLKZM5FiCj4asAD3NHW ia5lRTcm9NK0XN2ZeA5hQhZKylwyYdsbgNMnfvPc6DV7qt6jDhRdDgV/sgR1Ebjw/7xCxv IDff0O1ls3WFpJI7Ey7kvikkwL7abdk= 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-295-OBYXrK3VOBy-VYbXltdo7A-1; Tue, 26 Sep 2023 06:03:55 -0400 X-MC-Unique: OBYXrK3VOBy-VYbXltdo7A-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 84AFE8002B2; Tue, 26 Sep 2023 10:03:55 +0000 (UTC) Received: from amusil.redhat.com (unknown [10.45.224.62]) by smtp.corp.redhat.com (Postfix) with ESMTP id E57CF1054FC1; Tue, 26 Sep 2023 10:03:54 +0000 (UTC) From: Ales Musil To: dev@openvswitch.org Date: Tue, 26 Sep 2023 12:03:51 +0200 Message-ID: <20230926100352.136273-3-amusil@redhat.com> In-Reply-To: <20230926100352.136273-1-amusil@redhat.com> References: <20230926100352.136273-1-amusil@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: i.maximets@ovn.org Subject: [ovs-dev] [PATCH v2 2/3] vswitchd, ofproto-dpif: Propagate the CT limit from database 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" Progpagate the CT limit that is present in the DB into datapath. The limit is currently only propagated on change and can be overwritten by the dpctl commands. Signed-off-by: Ales Musil --- ofproto/ofproto-dpif.c | 39 ++++++++++++++++++++++++++++++++ ofproto/ofproto-dpif.h | 5 +++++ ofproto/ofproto-provider.h | 5 +++++ ofproto/ofproto.c | 16 +++++++++++-- ofproto/ofproto.h | 2 ++ tests/system-traffic.at | 46 +++++++++++++++++++++++++++++++++++++- vswitchd/bridge.c | 9 ++++++++ 7 files changed, 119 insertions(+), 3 deletions(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index ba5706f6a..55eaeefa3 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -220,6 +220,7 @@ static void ofproto_unixctl_init(void); static void ct_zone_config_init(struct dpif_backer *backer); static void ct_zone_config_uninit(struct dpif_backer *backer); static void ct_zone_timeout_policy_sweep(struct dpif_backer *backer); +static void ct_zone_limits_commit(struct dpif_backer *backer); static inline struct ofproto_dpif * ofproto_dpif_cast(const struct ofproto *ofproto) @@ -513,6 +514,7 @@ type_run(const char *type) process_dpif_port_changes(backer); ct_zone_timeout_policy_sweep(backer); + ct_zone_limits_commit(backer); return 0; } @@ -5522,6 +5524,8 @@ ct_zone_config_init(struct dpif_backer *backer) cmap_init(&backer->ct_zones); hmap_init(&backer->ct_tps); ovs_list_init(&backer->ct_tp_kill_list); + ovs_list_init(&backer->ct_zone_limits_to_add); + ovs_list_init(&backer->ct_zone_limits_to_del); clear_existing_ct_timeout_policies(backer); } @@ -5545,6 +5549,8 @@ ct_zone_config_uninit(struct dpif_backer *backer) id_pool_destroy(backer->tp_ids); cmap_destroy(&backer->ct_zones); hmap_destroy(&backer->ct_tps); + ct_dpif_free_zone_limits(&backer->ct_zone_limits_to_add); + ct_dpif_free_zone_limits(&backer->ct_zone_limits_to_del); } static void @@ -5625,6 +5631,38 @@ ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone_id) } } +static void +ct_zone_limit_update(const char *datapath_type, uint16_t zone_id, + int64_t *limit) +{ + struct dpif_backer *backer = shash_find_data(&all_dpif_backers, + datapath_type); + if (!backer) { + return; + } + + if (limit) { + ct_dpif_push_zone_limit(&backer->ct_zone_limits_to_add, zone_id, + *limit, 0); + } else { + ct_dpif_push_zone_limit(&backer->ct_zone_limits_to_del, zone_id, 0, 0); + } +} + +static void +ct_zone_limits_commit(struct dpif_backer *backer) +{ + if (!ovs_list_is_empty(&backer->ct_zone_limits_to_add)) { + ct_dpif_set_limits(backer->dpif, NULL, &backer->ct_zone_limits_to_add); + ct_dpif_free_zone_limits(&backer->ct_zone_limits_to_add); + } + + if (!ovs_list_is_empty(&backer->ct_zone_limits_to_del)) { + ct_dpif_del_limits(backer->dpif, &backer->ct_zone_limits_to_del); + ct_dpif_free_zone_limits(&backer->ct_zone_limits_to_del); + } +} + static void get_datapath_cap(const char *datapath_type, struct smap *cap) { @@ -6914,4 +6952,5 @@ const struct ofproto_class ofproto_dpif_class = { ct_flush, /* ct_flush */ ct_set_zone_timeout_policy, ct_del_zone_timeout_policy, + ct_zone_limit_update, }; diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index d8e0cd37a..b863dd6fc 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -284,6 +284,11 @@ struct dpif_backer { feature than 'bt_support'. */ struct atomic_count tnl_count; + + struct ovs_list ct_zone_limits_to_add; /* CT zone limits queued for + * addition into datapath. */ + struct ovs_list ct_zone_limits_to_del; /* CT zone limt queued for + * deletion from datapath. */ }; /* All existing ofproto_backer instances, indexed by ofproto->up.type. */ diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 9f7b8b6e8..5604aa65b 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1921,6 +1921,11 @@ struct ofproto_class { /* Deletes the timeout policy associated with 'zone' in datapath type * 'dp_type'. */ void (*ct_del_zone_timeout_policy)(const char *dp_type, uint16_t zone); + + /* Queues the CT zone limit update. In order for this change to take + * effect it needs to be commited. */ + void (*ct_zone_limit_update)(const char *dp_type, uint16_t zone, + int64_t *limit); }; extern const struct ofproto_class ofproto_dpif_class; diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index e78c80d11..484265ef9 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1026,6 +1026,18 @@ ofproto_ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone_id) } +void +ofproto_ct_zone_limit_update(const char *datapath_type, uint16_t zone_id, + int64_t *limit) +{ + datapath_type = ofproto_normalize_type(datapath_type); + const struct ofproto_class *class = ofproto_class_find__(datapath_type); + + if (class && class->ct_zone_limit_update) { + class->ct_zone_limit_update(datapath_type, zone_id, limit); + } +} + /* Spanning Tree Protocol (STP) configuration. */ @@ -6366,7 +6378,7 @@ handle_flow_mod__(struct ofproto *ofproto, const struct ofputil_flow_mod *fm, error = ofproto_flow_mod_start(ofproto, &ofm); if (!error) { ofproto_bump_tables_version(ofproto); - error = ofproto_flow_mod_finish(ofproto, &ofm, req); + error = ofproto_flow_mod_finish(ofproto, &ofm, req); ofmonitor_flush(ofproto->connmgr); } ovs_mutex_unlock(&ofproto_mutex); @@ -8437,7 +8449,7 @@ do_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags) /* Send error referring to the original message. */ ofconn_send_error(ofconn, be->msg, error); error = OFPERR_OFPBFC_MSG_FAILED; - + /* 2. Revert. Undo all the changes made above. */ LIST_FOR_EACH_REVERSE_CONTINUE(be, node, &bundle->msg_list) { if (be->type == OFPTYPE_FLOW_MOD) { diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 8efdb20a0..700a6f087 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -384,6 +384,8 @@ void ofproto_ct_set_zone_timeout_policy(const char *datapath_type, struct simap *timeout_policy); void ofproto_ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone); +void ofproto_ct_zone_limit_update(const char *datapath_type, uint16_t zone_id, + int64_t *limit); void ofproto_get_datapath_cap(const char *datapath_type, struct smap *dp_cap); diff --git a/tests/system-traffic.at b/tests/system-traffic.at index 418cd32fe..537db66e0 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -5195,9 +5195,53 @@ udp,orig=(src=10.1.1.3,dst=10.1.1.4,sport=1,dport=3),reply=(src=10.1.1.4,dst=10. udp,orig=(src=10.1.1.3,dst=10.1.1.4,sport=1,dport=4),reply=(src=10.1.1.4,dst=10.1.1.3,sport=4,dport=1),zone=3 ]) +dnl Test limit set via database. +VSCTL_ADD_DATAPATH_TABLE() + +AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=0]) +AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=3]) + +AT_CHECK([ovs-appctl dpctl/ct-del-limits zone=3]) +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl +default limit=10 +zone=0,limit=5,count=0 +]) + +AT_CHECK([ovs-vsctl add-zone-limit $DP_TYPE zone=0 limit=3]) +AT_CHECK([ovs-vsctl add-zone-limit $DP_TYPE zone=3 limit=3]) + +OVS_WAIT_UNTIL_EQUAL([ovs-appctl dpctl/ct-get-limits], [dnl +default limit=10 +zone=0,limit=3,count=0 +zone=3,limit=3,count=0]) + +AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 packet=50540000000a50540000000908004500001c000000000011a4c90a0101030a0101040001000200080000 actions=resubmit(,0)"]) +AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 packet=50540000000a50540000000908004500001c000000000011a4c90a0101030a0101040001000300080000 actions=resubmit(,0)"]) +AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 packet=50540000000a50540000000908004500001c000000000011a4c90a0101030a0101040001000400080000 actions=resubmit(,0)"]) +AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 packet=50540000000a50540000000908004500001c000000000011a4c90a0101030a0101040001000500080000 actions=resubmit(,0)"]) +AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 packet=50540000000a50540000000908004500001c000000000011a4c90a0101030a0101040001000600080000 actions=resubmit(,0)"]) + +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=10\.1\.1\.3," | sort ], [0], [dnl +udp,orig=(src=10.1.1.3,dst=10.1.1.4,sport=1,dport=2),reply=(src=10.1.1.4,dst=10.1.1.3,sport=2,dport=1),zone=3 +udp,orig=(src=10.1.1.3,dst=10.1.1.4,sport=1,dport=3),reply=(src=10.1.1.4,dst=10.1.1.3,sport=3,dport=1),zone=3 +udp,orig=(src=10.1.1.3,dst=10.1.1.4,sport=1,dport=4),reply=(src=10.1.1.4,dst=10.1.1.3,sport=4,dport=1),zone=3 +]) + +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl +default limit=10 +zone=0,limit=3,count=0 +zone=3,limit=3,count=3 +]) + +AT_CHECK([ovs-vsctl del-zone-limit $DP_TYPE zone=3]) +OVS_WAIT_UNTIL_EQUAL([ovs-appctl dpctl/ct-get-limits], [dnl +default limit=10 +zone=0,limit=3,count=0]) + OVS_TRAFFIC_VSWITCHD_STOP(["dnl /could not create datapath/d -/(Cannot allocate memory) on packet/d"]) +/(Cannot allocate memory) on packet/d +/failed to .* timeout policy/d"]) AT_CLEANUP AT_SETUP([FTP - no conntrack]) diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index e9110c1d8..6cd09e145 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -157,6 +157,7 @@ struct aa_mapping { /* Internal representation of conntrack zone configuration table in OVSDB. */ struct ct_zone { uint16_t zone_id; + int64_t limit; /* Limit of allowed entries. */ struct simap tp; /* A map from timeout policy attribute to * timeout value. */ struct hmap_node node; /* Node in 'struct datapath' 'ct_zones' @@ -756,6 +757,13 @@ ct_zones_reconfigure(struct datapath *dp, struct ovsrec_datapath *dp_cfg) ofproto_ct_set_zone_timeout_policy(dp->type, ct_zone->zone_id, &ct_zone->tp); } + + int64_t desired_limit = zone_cfg->limit ? *zone_cfg->limit : -1; + if (ct_zone->limit != desired_limit) { + ofproto_ct_zone_limit_update(dp->type, zone_id, zone_cfg->limit); + } + + ct_zone->limit = desired_limit; ct_zone->last_used = idl_seqno; } @@ -763,6 +771,7 @@ ct_zones_reconfigure(struct datapath *dp, struct ovsrec_datapath *dp_cfg) HMAP_FOR_EACH_SAFE (ct_zone, node, &dp->ct_zones) { if (ct_zone->last_used != idl_seqno) { ofproto_ct_del_zone_timeout_policy(dp->type, ct_zone->zone_id); + ofproto_ct_zone_limit_update(dp->type, ct_zone->zone_id, NULL); ct_zone_remove_and_destroy(dp, ct_zone); } } From patchwork Tue Sep 26 10:03:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Musil X-Patchwork-Id: 1839587 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=IlRCnF1G; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RvwM11GT3z1ypM for ; Tue, 26 Sep 2023 20:04:13 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 30223417F9; Tue, 26 Sep 2023 10:04:10 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 30223417F9 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=IlRCnF1G 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 nLGm6luZ3_JI; Tue, 26 Sep 2023 10:04:06 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id 1A326417D4; Tue, 26 Sep 2023 10:04:05 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 1A326417D4 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1CEB0C0DDB; Tue, 26 Sep 2023 10:04:02 +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 7B284C0032 for ; Tue, 26 Sep 2023 10:04:00 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 5611A60AB7 for ; Tue, 26 Sep 2023 10:04:00 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 5611A60AB7 Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=IlRCnF1G 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 AsueraJPAPNe for ; Tue, 26 Sep 2023 10:03:59 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id 0AB9060BD6 for ; Tue, 26 Sep 2023 10:03:58 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 0AB9060BD6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1695722638; 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=tTyX91ykdKlbUaVynEigoGxIBgwbftCf22gOvWGlNFk=; b=IlRCnF1G41ecgVZ2noTNO3i+nynofXvxOInSGVTFK46HHDJuiWIo6xbXd1ibDeOWFrvEVu pyXrA/hQHFqlnh1HVgmwWYSTm0dV5/IBLMAqr+kz6HNgAxwz610SUeFlGqJECQTa7X55X9 uj4J4seTrCmRyF4441vLahnvahhotk4= Received: from mimecast-mx02.redhat.com (mx-ext.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-529-G6Abg8l1MtGItU_plzkxCQ-1; Tue, 26 Sep 2023 06:03:56 -0400 X-MC-Unique: G6Abg8l1MtGItU_plzkxCQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 75B851C0519D; Tue, 26 Sep 2023 10:03:56 +0000 (UTC) Received: from amusil.redhat.com (unknown [10.45.224.62]) by smtp.corp.redhat.com (Postfix) with ESMTP id BA4CD1054FC1; Tue, 26 Sep 2023 10:03:55 +0000 (UTC) From: Ales Musil To: dev@openvswitch.org Date: Tue, 26 Sep 2023 12:03:52 +0200 Message-ID: <20230926100352.136273-4-amusil@redhat.com> In-Reply-To: <20230926100352.136273-1-amusil@redhat.com> References: <20230926100352.136273-1-amusil@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: i.maximets@ovn.org Subject: [ovs-dev] [PATCH v2 3/3] netlink, netdev: Enforce CT limit protection 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" Enforce the CT limit protection, it ensures that any CT limit value that was set by forced operation, currently the DB CT limit, will be protected against overwrite from other sources, e.g. the dpctl command. Signed-off-by: Ales Musil Acked-by: Simon Horman --- lib/conntrack.c | 51 ++++++++++++++++++++++++++--------------- lib/conntrack.h | 5 ++-- lib/ct-dpif.c | 9 ++++---- lib/ct-dpif.h | 5 ++-- lib/dpctl.c | 4 ++-- lib/dpif-netdev.c | 12 ++++++---- lib/dpif-netlink.c | 37 ++++++++++++++++++++++++++---- lib/dpif-provider.h | 13 +++++++---- ofproto/ofproto-dpif.c | 6 +++-- tests/system-traffic.at | 28 ++++++++++++++++++++++ 10 files changed, 126 insertions(+), 44 deletions(-) diff --git a/lib/conntrack.c b/lib/conntrack.c index 47a443fba..b5b5d4a4c 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -85,6 +85,7 @@ enum ct_alg_ctl_type { struct zone_limit { struct cmap_node node; struct conntrack_zone_limit czl; + bool limit_protected; }; static bool conn_key_extract(struct conntrack *, struct dp_packet *, @@ -344,17 +345,13 @@ zone_limit_get(struct conntrack *ct, int32_t zone) } static int -zone_limit_create(struct conntrack *ct, int32_t zone, uint32_t limit) +zone_limit_create(struct conntrack *ct, int32_t zone, uint32_t limit, + bool limit_protected) OVS_REQUIRES(ct->ct_lock) { - struct zone_limit *zl = zone_limit_lookup_protected(ct, zone); - - if (zl) { - return 0; - } - if (zone >= DEFAULT_ZONE && zone <= MAX_ZONE) { - zl = xzalloc(sizeof *zl); + struct zone_limit *zl = xzalloc(sizeof *zl); + zl->limit_protected = limit_protected; zl->czl.limit = limit; zl->czl.zone = zone; zl->czl.zone_limit_seq = ct->zone_limit_seq++; @@ -366,18 +363,28 @@ zone_limit_create(struct conntrack *ct, int32_t zone, uint32_t limit) } } +static inline bool +can_update_zone_limit(struct zone_limit *zl, bool force) +{ + return !(zl && zl->limit_protected && !force); +} + int -zone_limit_update(struct conntrack *ct, int32_t zone, uint32_t limit) +zone_limit_update(struct conntrack *ct, int32_t zone, uint32_t limit, + bool force) { int err = 0; - struct zone_limit *zl = zone_limit_lookup(ct, zone); - if (zl) { + ovs_mutex_lock(&ct->ct_lock); + + struct zone_limit *zl = zone_limit_lookup_protected(ct, zone); + if (!can_update_zone_limit(zl, force)) { + err = EPERM; + } else if (zl) { zl->czl.limit = limit; + zl->limit_protected = force; VLOG_INFO("Changed zone limit of %u for zone %d", limit, zone); } else { - ovs_mutex_lock(&ct->ct_lock); - err = zone_limit_create(ct, zone, limit); - ovs_mutex_unlock(&ct->ct_lock); + err = zone_limit_create(ct, zone, limit, force); if (!err) { VLOG_INFO("Created zone limit of %u for zone %d", limit, zone); } else { @@ -385,6 +392,8 @@ zone_limit_update(struct conntrack *ct, int32_t zone, uint32_t limit) zone); } } + + ovs_mutex_unlock(&ct->ct_lock); return err; } @@ -398,20 +407,24 @@ zone_limit_clean(struct conntrack *ct, struct zone_limit *zl) } int -zone_limit_delete(struct conntrack *ct, uint16_t zone) +zone_limit_delete(struct conntrack *ct, uint16_t zone, bool force) { + int err = 0; ovs_mutex_lock(&ct->ct_lock); + struct zone_limit *zl = zone_limit_lookup_protected(ct, zone); - if (zl) { + if (!can_update_zone_limit(zl, force)) { + err = EPERM; + } else if (zl) { zone_limit_clean(ct, zl); - ovs_mutex_unlock(&ct->ct_lock); VLOG_INFO("Deleted zone limit for zone %d", zone); } else { - ovs_mutex_unlock(&ct->ct_lock); VLOG_INFO("Attempted delete of non-existent zone limit: zone %d", zone); } - return 0; + + ovs_mutex_unlock(&ct->ct_lock); + return err; } static void diff --git a/lib/conntrack.h b/lib/conntrack.h index 57d5159b6..a58a800f9 100644 --- a/lib/conntrack.h +++ b/lib/conntrack.h @@ -153,7 +153,8 @@ bool conntrack_get_tcp_seq_chk(struct conntrack *ct); struct ipf *conntrack_ipf_ctx(struct conntrack *ct); struct conntrack_zone_limit zone_limit_get(struct conntrack *ct, int32_t zone); -int zone_limit_update(struct conntrack *ct, int32_t zone, uint32_t limit); -int zone_limit_delete(struct conntrack *ct, uint16_t zone); +int zone_limit_update(struct conntrack *ct, int32_t zone, uint32_t limit, + bool force); +int zone_limit_delete(struct conntrack *ct, uint16_t zone, bool force); #endif /* conntrack.h */ diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c index f59c6e560..335ba09f9 100644 --- a/lib/ct-dpif.c +++ b/lib/ct-dpif.c @@ -399,11 +399,11 @@ ct_dpif_get_tcp_seq_chk(struct dpif *dpif, bool *enabled) int ct_dpif_set_limits(struct dpif *dpif, const uint32_t *default_limit, - const struct ovs_list *zone_limits) + const struct ovs_list *zone_limits, bool force) { return (dpif->dpif_class->ct_set_limits ? dpif->dpif_class->ct_set_limits(dpif, default_limit, - zone_limits) + zone_limits, force) : EOPNOTSUPP); } @@ -420,10 +420,11 @@ ct_dpif_get_limits(struct dpif *dpif, uint32_t *default_limit, } int -ct_dpif_del_limits(struct dpif *dpif, const struct ovs_list *zone_limits) +ct_dpif_del_limits(struct dpif *dpif, const struct ovs_list *zone_limits, + bool force) { return (dpif->dpif_class->ct_del_limits - ? dpif->dpif_class->ct_del_limits(dpif, zone_limits) + ? dpif->dpif_class->ct_del_limits(dpif, zone_limits, force) : EOPNOTSUPP); } diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h index 0b728b529..0b74ec463 100644 --- a/lib/ct-dpif.h +++ b/lib/ct-dpif.h @@ -308,10 +308,11 @@ int ct_dpif_get_nconns(struct dpif *dpif, uint32_t *nconns); int ct_dpif_set_tcp_seq_chk(struct dpif *dpif, bool enabled); int ct_dpif_get_tcp_seq_chk(struct dpif *dpif, bool *enabled); int ct_dpif_set_limits(struct dpif *dpif, const uint32_t *default_limit, - const struct ovs_list *); + const struct ovs_list *, bool enforced); int ct_dpif_get_limits(struct dpif *dpif, uint32_t *default_limit, const struct ovs_list *, struct ovs_list *); -int ct_dpif_del_limits(struct dpif *dpif, const struct ovs_list *); +int ct_dpif_del_limits(struct dpif *dpif, const struct ovs_list *, + bool enforced); int ct_dpif_sweep(struct dpif *, uint32_t *ms); int ct_dpif_ipf_set_enabled(struct dpif *, bool v6, bool enable); int ct_dpif_ipf_set_min_frag(struct dpif *, bool v6, uint32_t min_frag); diff --git a/lib/dpctl.c b/lib/dpctl.c index cd12625a1..e498c29ce 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -2233,7 +2233,7 @@ dpctl_ct_set_limits(int argc, const char *argv[], ct_dpif_push_zone_limit(&zone_limits, zone, limit, 0); } - error = ct_dpif_set_limits(dpif, p_default_limit, &zone_limits); + error = ct_dpif_set_limits(dpif, p_default_limit, &zone_limits, false); if (!error) { ct_dpif_free_zone_limits(&zone_limits); dpif_close(dpif); @@ -2300,7 +2300,7 @@ dpctl_ct_del_limits(int argc, const char *argv[], goto error; } - error = ct_dpif_del_limits(dpif, &zone_limits); + error = ct_dpif_del_limits(dpif, &zone_limits, false); if (!error) { goto out; } else { diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 157694bcf..90a48baa6 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -9447,12 +9447,14 @@ dpif_netdev_ct_get_sweep_interval(struct dpif *dpif, uint32_t *ms) static int dpif_netdev_ct_set_limits(struct dpif *dpif, const uint32_t *default_limits, - const struct ovs_list *zone_limits) + const struct ovs_list *zone_limits, + bool force) { int err = 0; struct dp_netdev *dp = get_dp_netdev(dpif); if (default_limits) { - err = zone_limit_update(dp->conntrack, DEFAULT_ZONE, *default_limits); + err = zone_limit_update(dp->conntrack, DEFAULT_ZONE, *default_limits, + force); if (err != 0) { return err; } @@ -9461,7 +9463,7 @@ dpif_netdev_ct_set_limits(struct dpif *dpif, struct ct_dpif_zone_limit *zone_limit; LIST_FOR_EACH (zone_limit, node, zone_limits) { err = zone_limit_update(dp->conntrack, zone_limit->zone, - zone_limit->limit); + zone_limit->limit, force); if (err != 0) { break; } @@ -9512,13 +9514,13 @@ dpif_netdev_ct_get_limits(struct dpif *dpif, static int dpif_netdev_ct_del_limits(struct dpif *dpif, - const struct ovs_list *zone_limits) + const struct ovs_list *zone_limits, bool force) { int err = 0; struct dp_netdev *dp = get_dp_netdev(dpif); struct ct_dpif_zone_limit *zone_limit; LIST_FOR_EACH (zone_limit, node, zone_limits) { - err = zone_limit_delete(dp->conntrack, zone_limit->zone); + err = zone_limit_delete(dp->conntrack, zone_limit->zone, force); if (err != 0) { break; } diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 9194971d3..8ef5ce87f 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -250,6 +250,10 @@ static int ovs_ct_limit_family; * Initialized by dpif_netlink_init(). */ static unsigned int ovs_vport_mcgroup; +/* CT limit protection, must be global for all 'struct dpif_netlink' + * instances. */ +static unsigned long ct_limit_protection[BITMAP_N_LONGS(UINT16_MAX)] = {0}; + /* If true, tunnel devices are created using OVS compat/genetlink. * If false, tunnel devices are created with rtnetlink and using light weight * tunnels. If we fail to create the tunnel the rtnetlink+LWT, then we fallback @@ -3358,15 +3362,35 @@ dpif_netlink_ct_flush(struct dpif *dpif OVS_UNUSED, const uint16_t *zone, } } +static int +update_zone_limit_protection(const struct ovs_list *limits, bool force) +{ + struct ct_dpif_zone_limit *zone_limit; + LIST_FOR_EACH (zone_limit, node, limits) { + if (bitmap_is_set(ct_limit_protection, zone_limit->zone) && + !force) { + return EPERM; + } + bitmap_set(ct_limit_protection, zone_limit->zone, force); + } + + return 0; +} + static int dpif_netlink_ct_set_limits(struct dpif *dpif OVS_UNUSED, const uint32_t *default_limits, - const struct ovs_list *zone_limits) + const struct ovs_list *zone_limits, bool force) { if (ovs_ct_limit_family < 0) { return EOPNOTSUPP; } + int err = update_zone_limit_protection(zone_limits, force); + if (err) { + return err; + } + struct ofpbuf *request = ofpbuf_new(NL_DUMP_BUFSIZE); nl_msg_put_genlmsghdr(request, 0, ovs_ct_limit_family, NLM_F_REQUEST | NLM_F_ECHO, OVS_CT_LIMIT_CMD_SET, @@ -3399,7 +3423,7 @@ dpif_netlink_ct_set_limits(struct dpif *dpif OVS_UNUSED, } nl_msg_end_nested(request, opt_offset); - int err = nl_transact(NETLINK_GENERIC, request, NULL); + err = nl_transact(NETLINK_GENERIC, request, NULL); ofpbuf_delete(request); return err; } @@ -3508,12 +3532,17 @@ out: static int dpif_netlink_ct_del_limits(struct dpif *dpif OVS_UNUSED, - const struct ovs_list *zone_limits) + const struct ovs_list *zone_limits, bool force) { if (ovs_ct_limit_family < 0) { return EOPNOTSUPP; } + int err = update_zone_limit_protection(zone_limits, force); + if (err) { + return err; + } + struct ofpbuf *request = ofpbuf_new(NL_DUMP_BUFSIZE); nl_msg_put_genlmsghdr(request, 0, ovs_ct_limit_family, NLM_F_REQUEST | NLM_F_ECHO, OVS_CT_LIMIT_CMD_DEL, @@ -3537,7 +3566,7 @@ dpif_netlink_ct_del_limits(struct dpif *dpif OVS_UNUSED, nl_msg_end_nested(request, opt_offset); } - int err = nl_transact(NETLINK_GENERIC, request, NULL); + err = nl_transact(NETLINK_GENERIC, request, NULL); ofpbuf_delete(request); return err; diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index 1b822cb07..6c292856f 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -521,9 +521,11 @@ struct dpif_class { /* Sets the max connections allowed per zone according to 'zone_limits', * a list of 'struct ct_dpif_zone_limit' entries (the 'count' member * is not used when setting limits). If 'default_limit' is not NULL, - * modifies the default limit to '*default_limit'. */ + * modifies the default limit to '*default_limit'. If 'force' is set + * to 'true' it will overwrite current configuration, otherwise it can + * return 'EPERM' if the limit is already enforced for this zone. */ int (*ct_set_limits)(struct dpif *, const uint32_t *default_limit, - const struct ovs_list *zone_limits); + const struct ovs_list *zone_limits, bool force); /* Looks up the default per zone limit and stores that in * 'default_limit'. Look up the per zone limits for all zones in @@ -536,8 +538,11 @@ struct dpif_class { struct ovs_list *zone_limits_out); /* Deletes per zone limit of all zones specified in 'zone_limits', a - * list of 'struct ct_dpif_zone_limit' entries. */ - int (*ct_del_limits)(struct dpif *, const struct ovs_list *zone_limits); + * list of 'struct ct_dpif_zone_limit' entries. If 'force' is set + * to 'true' it will remove current configuration, otherwise it + * returns 'EPERM' if the limit is already enforced for this zone.*/ + int (*ct_del_limits)(struct dpif *, const struct ovs_list *zone_limits, + bool force); /* Connection tracking timeout policy */ diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 55eaeefa3..96149ad8d 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -5653,12 +5653,14 @@ static void ct_zone_limits_commit(struct dpif_backer *backer) { if (!ovs_list_is_empty(&backer->ct_zone_limits_to_add)) { - ct_dpif_set_limits(backer->dpif, NULL, &backer->ct_zone_limits_to_add); + ct_dpif_set_limits(backer->dpif, NULL, &backer->ct_zone_limits_to_add, + true); ct_dpif_free_zone_limits(&backer->ct_zone_limits_to_add); } if (!ovs_list_is_empty(&backer->ct_zone_limits_to_del)) { - ct_dpif_del_limits(backer->dpif, &backer->ct_zone_limits_to_del); + ct_dpif_del_limits(backer->dpif, &backer->ct_zone_limits_to_del, + true); ct_dpif_free_zone_limits(&backer->ct_zone_limits_to_del); } } diff --git a/tests/system-traffic.at b/tests/system-traffic.at index 537db66e0..8eb609675 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -5238,6 +5238,34 @@ OVS_WAIT_UNTIL_EQUAL([ovs-appctl dpctl/ct-get-limits], [dnl default limit=10 zone=0,limit=3,count=0]) +dnl Try to overwrite the zone limit via dpctl command. +AT_CHECK([ovs-appctl dpctl/ct-set-limits zone=0,limit=5], [2], [ignore], [ignore]) + +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl +default limit=10 +zone=0,limit=3,count=0 +]) + +AT_CHECK([ovs-appctl dpctl/ct-del-limits zone=0], [2], [ignore], [ignore]) +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl +default limit=10 +zone=0,limit=3,count=0 +]) + +dnl Set limit for zone that is not in DB via dpctl command. +AT_CHECK([ovs-appctl dpctl/ct-set-limits zone=1,limit=5]) +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl +default limit=10 +zone=0,limit=3,count=0 +zone=1,limit=5,count=0 +]) + +AT_CHECK([ovs-appctl dpctl/ct-del-limits zone=1]) +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl +default limit=10 +zone=0,limit=3,count=0 +]) + OVS_TRAFFIC_VSWITCHD_STOP(["dnl /could not create datapath/d /(Cannot allocate memory) on packet/d