From patchwork Thu Aug 1 22:07:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 1140788 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Hy+fkmre"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4604Df5WTmz9s3Z for ; Fri, 2 Aug 2019 08:08:18 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id CA9FE1560; Thu, 1 Aug 2019 22:07:45 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 4BB54103C for ; Thu, 1 Aug 2019 22:07:44 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id DFFCF82B for ; Thu, 1 Aug 2019 22:07:42 +0000 (UTC) Received: by mail-wm1-f68.google.com with SMTP id l2so64471376wmg.0 for ; Thu, 01 Aug 2019 15:07:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=JAxa1P/24RmZCA6OVqrRHv31sle9xnRS3Hl/1yHPbU0=; b=Hy+fkmrelg9pjvlpKAWc9z5a7QHoSsYa/RL72co7Cu6bxmEvESx7qJMk/oiO1vlXq5 Js0nUD9Ehgh1hRM47V+Kj+x6j+ZKDDyxHbU8AJAEbS88UWMYmJ9Ue0rcCqiaZZ/p0xfE AobcYbp1nIo5h3j983MGIw9QGeaPaqpzPBfTdQVFF/BD5Hjftrvg8Wae7ZBvSFj9AwDQ 0Ifqv5Dk9nXBm5HSnPMnyp9/5Ye0woR2dgOPQmaoIjlX4tpGAFKPVDvFVY89ZvZWjQ95 JLT1dhJC4IET9BG42ep9FCisvNbPWVMlatH1RFKG2wzlhIrxn0oaj2bGt5BmB2zsXICO gw/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=JAxa1P/24RmZCA6OVqrRHv31sle9xnRS3Hl/1yHPbU0=; b=C/asdoQNXL42i/12EvHtP8QiUaOAC8RMQWY9ifbRax49pbJDcnUWUB8estMrkqhNkG UiS6d1JmGEuoeA29p2EKpy8AIWj5GzuORQorNXPoyLebLhnC7Z4Zka451RfHuIFCZv6t eQDJ5MY6CVEwDjATKDyEKhpT70ykm+17sk+H8Z/+Rpn5S9TDmmFFbzTc4eVXhR/kL17k h33F7Hfk2B7J4FDY6PEzOXe0jD04zkOSC8Qmt9ygpiXIC3U5ymCzE8ZwQx5xM+AF5wFd ZjnDmU6X3qYW0DoW7x6TVMsn+oaBX/Wt+eoCVvUZv1Vzi57btZnP0EfR26KpbAVyz7wi SbYw== X-Gm-Message-State: APjAAAVr4jA9Vovg2XnY+wrqp6Eq/M+eDk944UsmZ/jdaRWKYk6hQc/r dflzK2jAUgVshThvmLTevqYExRTg X-Google-Smtp-Source: APXvYqySVwrG16Njsa1gvpgWfBAb7cK4uMQywq8yrfCa+fPLuxt7DZ/6Ss1EOBkje6pddMsWWK5hmQ== X-Received: by 2002:a05:600c:228f:: with SMTP id 15mr527920wmf.60.1564697261085; Thu, 01 Aug 2019 15:07:41 -0700 (PDT) Received: from vm-main.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id z19sm54128982wmi.7.2019.08.01.15.07.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Aug 2019 15:07:40 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Thu, 1 Aug 2019 15:07:25 -0700 Message-Id: <1564697253-37992-2-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> References: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 1/9] ovs-vswitchd: Add Datapath, CT_Zone, and CT_Zone_Policy tables. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Justin Pettit From: Justin Pettit Signed-off-by: Justin Pettit --- vswitchd/vswitch.ovsschema | 43 +++++++- vswitchd/vswitch.xml | 252 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 246 insertions(+), 49 deletions(-) diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index f7c6eb8983cd..d215f4edfefa 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,9 +1,14 @@ {"name": "Open_vSwitch", - "version": "8.0.0", - "cksum": "3962141869 23978", + "version": "8.1.0", + "cksum": "1566974404 25483", "tables": { "Open_vSwitch": { "columns": { + "datapaths": { + "type": {"key": {"type": "string"}, + "value": {"type": "uuid", + "refTable": "Datapath"}, + "min": 0, "max": "unlimited"}}, "bridges": { "type": {"key": {"type": "uuid", "refTable": "Bridge"}, @@ -629,6 +634,40 @@ "min": 0, "max": "unlimited"}, "ephemeral": true}}, "indexes": [["target"]]}, + "Datapath": { + "columns": { + "datapath_version": { + "type": "string"}, + "ct_zones": { + "type": {"key": {"type": "integer", + "minInteger": 0, + "maxInteger": 65535}, + "value": {"type": "uuid", + "refTable": "CT_Zone"}, + "min": 0, "max": "unlimited"}}, + "external_ids": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}}, + "CT_Zone": { + "columns": { + "timeout_policy": { + "type": {"key": {"type": "uuid", + "refTable": "CT_Timeout_Policy"}, + "min": 0, "max": 1}}, + "external_ids": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}}, + "CT_Timeout_Policy": { + "columns": { + "timeouts": { + "type": {"key": "string", + "value": {"type" : "integer", + "minInteger" : 0, + "maxInteger" : 4294967295}, + "min": 0, "max": "unlimited"}}, + "external_ids": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}}, "SSL": { "columns": { "private_key": { diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 027aee2f523b..a0706c9c0fc1 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -52,6 +52,13 @@ one record in the table. + + Map of datapath types to datapaths. The + column of the + table is used as a key for this map. The value points to a row in + the table. + + Set of bridges managed by the daemon. @@ -1192,53 +1199,11 @@ -

- Reports the version number of the Open vSwitch datapath in use. - This allows management software to detect and report discrepancies - between Open vSwitch userspace and datapath versions. (The column in the reports the Open vSwitch userspace version.) - The version reported depends on the datapath in use: -

- -
    -
  • - When the kernel module included in the Open vSwitch source tree is - used, this column reports the Open vSwitch version from which the - module was taken. -
  • - -
  • - When the kernel module that is part of the upstream Linux kernel is - used, this column reports <unknown>. -
  • - -
  • - When the datapath is built into the ovs-vswitchd - binary, this column reports <built-in>. A - built-in datapath is by definition the same version as the rest of - the Open VSwitch userspace. -
  • - -
  • - Other datapaths (such as the Hyper-V kernel datapath) currently - report <unknown>. -
  • -
- -

- A version discrepancy between ovs-vswitchd and the - datapath in use is not normally cause for alarm. The Open vSwitch - kernel datapaths for Linux and Hyper-V, in particular, are designed - for maximum inter-version compatibility: any userspace version works - with with any kernel version. Some reasons do exist to insist on - particular user/kernel pairings. First, newer kernel versions add - new features, that can only be used by new-enough userspace, e.g. - VXLAN tunneling requires certain minimal userspace and kernel - versions. Second, as an extension to the first reason, some newer - kernel versions add new features for enhancing performance that only - new-enough userspace versions can take advantage of. -

+ Reports the datapath version. This column is maintained for + backwards compatibility. The preferred locatation is the + column of the + table. The full documentation for this + column is there.
@@ -5560,6 +5525,199 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
+ +

+ Configuration for a datapath within . +

+

+ A datapath is responsible for providing the packet handling in Open + vSwitch. There are two primary datapath implementations used by + Open vSwitch: kernel and userspace. Kernel datapath + implementations are available for Linux and Hyper-V, and selected + as system in the column + of the table. The userspace datapath is used + by DPDK and AF-XDP, and is selected as netdev in the + column of the + table. +

+

+ A datapath of a particular type is shared by all the bridges that use + that datapath. Thus, configurations applied to this table affect + all bridges that use this datapath. +

+ + +

+ Reports the version number of the Open vSwitch datapath in use. + This allows management software to detect and report discrepancies + between Open vSwitch userspace and datapath versions. (The column in the reports the Open vSwitch userspace version.) + The version reported depends on the datapath in use: +

+ +
    +
  • + When the kernel module included in the Open vSwitch source tree is + used, this column reports the Open vSwitch version from which the + module was taken. +
  • + +
  • + When the kernel module that is part of the upstream Linux kernel is + used, this column reports <unknown>. +
  • + +
  • + When the datapath is built into the ovs-vswitchd + binary, this column reports <built-in>. A + built-in datapath is by definition the same version as the rest of + the Open VSwitch userspace. +
  • + +
  • + Other datapaths (such as the Hyper-V kernel datapath) currently + report <unknown>. +
  • +
+ +

+ A version discrepancy between ovs-vswitchd and the + datapath in use is not normally cause for alarm. The Open vSwitch + kernel datapaths for Linux and Hyper-V, in particular, are designed + for maximum inter-version compatibility: any userspace version works + with with any kernel version. Some reasons do exist to insist on + particular user/kernel pairings. First, newer kernel versions add + new features, that can only be used by new-enough userspace, e.g. + VXLAN tunneling requires certain minimal userspace and kernel + versions. Second, as an extension to the first reason, some newer + kernel versions add new features for enhancing performance that only + new-enough userspace versions can take advantage of. +

+
+ + + Configuration for connection tracking zones. Each pair maps from a + zone id to a configuration for that zone. Zone 0 applies + to the default zone (ie, the one used if a zone is not specified in + connection tracking-related OpenFlow matches and actions). + + + + The overall purpose of these columns is described under Common + Columns at the beginning of this document. + + + +
+ + + Connection tracking zone configuration + + + Connection tracking timeout policy for this zone. If timeout policy is + not specified, defaults to the timeout policy in the system. + + + + The overall purpose of these columns is described under Common + Columns at the beginning of this document. + + + +
+ + + Connection tracking timeout policy configuration + + + + The timeouts column contains key-value pairs used + to configure connection tracking timeouts in a datapath. + Key-value pairs that are not supported by a datapath are + ignored. + + + + + TCP SYN sent timeout. + + + + TCP SYN receive timeout. + + + + TCP established timeout. + + + + TCP FIN wait timeout. + + + + TCP close wait timeout. + + + + TCP last ACK timeout. + + + + TCP time wait timeout. + + + + TCP close timeout. + + + + TCP syn sent2 timeout. + + + + TCP retransmit timeout. + + + + TCP unacknowledgment timeout. + + + + + + First UDP packet timeout. + + + + The timeout in the state that source host sends more than one packet + but the destination host has never sent one backs. + + + + UDP packets seen in both directions timeout. + + + + + + First ICMP timeout. + + + + ICMP reply timeout. + + + + + + The overall purpose of these columns is described under Common + Columns at the beginning of this document. + + + +
+ SSL configuration for an Open_vSwitch. From patchwork Thu Aug 1 22:07:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 1140789 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="SYtWGbHx"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4604FR0ghkz9s3Z for ; Fri, 2 Aug 2019 08:08:59 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 9C779156D; Thu, 1 Aug 2019 22:07:46 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id A48CF1560 for ; Thu, 1 Aug 2019 22:07:45 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 7611582B for ; Thu, 1 Aug 2019 22:07:44 +0000 (UTC) Received: by mail-wr1-f50.google.com with SMTP id 31so75175845wrm.1 for ; Thu, 01 Aug 2019 15:07:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=JsmeEyBsmhBkbyf42uZx2Yf04wkVFYBRddDDbAytB8Q=; b=SYtWGbHxDjR5T11IU1tf+RcG+PpA54m/krdAHpKFA5NK30339/MddAwWxmBnGAvUAy I6Cf2ny/cUMeSF25zwdPk8OVmeIuN4oYbHIs0zuLSAl7dBxkqRBthjZ5BsjuikTS/gPa 36Cwb7xPzDI5/NNsxtydcgEGYIoemcpKrUsY2dUQV0X0r0GG7FGfJ+vtej1mrD6p9CaI 4zb1frU+L41kWi5SATxq9I+/XQFI2oJGVm2HlshDcv/IGNmHVAdtX+8xA+pcas5EcshP NtwhOLxXQi/C7YmNqwBY7sEGhGcTkXskFKYB8F0ZiAed64kUqbMtikE8lUUgI3llC+Za 9Gfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=JsmeEyBsmhBkbyf42uZx2Yf04wkVFYBRddDDbAytB8Q=; b=dfOUYjCF1CcFMASfW/6AjDEXcZNnbmKb/4KsrffuM6oSeV3rL9Cg3iAvGjo17D1rQn bJAEGOvC4/xhx0G7P9lLexeydQiu9gYNUz6Clc47XSEoQziSSeI3/4HHgP1cpsPpU1qN HvKGILUmE2ve3qc/zfY4XGAWjzvujjBeK/ku2oW/F/9Tf4V7XBqqyooSBA1wndhkGh5X yyFmQHw3vy+tLYwUJvcff/6QJMRW6PkB4QUySYhc6plZ+Ri5yvyY4NjX/m1r7s0SOtdG sXqCFuEYsrTYzyFTSbCqPaUUOxzWF0+B8L5h7eicEcEzbYOUdVRI3z/SGC+a9MqWa3lj e37Q== X-Gm-Message-State: APjAAAW44A5RrwuCaI9MlD/rPzqq3e03j7Kz3mG4ayrPxjO3Vc00hh+S pAZIcQ0JqFf1gmyIDmOsOH1fcSwE X-Google-Smtp-Source: APXvYqxnxqFtzo57iLSboIdQ4dx8EeO7p5uUzolHWQanlvAqSyF9MWgsoUFVZ9mJWMwXR1GKOxDUxw== X-Received: by 2002:adf:8bc2:: with SMTP id w2mr59630255wra.7.1564697262576; Thu, 01 Aug 2019 15:07:42 -0700 (PDT) Received: from vm-main.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id z19sm54128982wmi.7.2019.08.01.15.07.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Aug 2019 15:07:42 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Thu, 1 Aug 2019 15:07:26 -0700 Message-Id: <1564697253-37992-3-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> References: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 2/9] ovs-vsctl: Add conntrack zone commands. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu The patch adds commands creating/deleting/listing conntrack zone timeout policies: $ ovs-vsctl {add,del,list}-zone-tp zone=zone_id ... Signed-off-by: William Tu Acked-by: Justin Pettit --- tests/ovs-vsctl.at | 34 +++++++- utilities/ovs-vsctl.8.in | 25 ++++++ utilities/ovs-vsctl.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+), 2 deletions(-) diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at index 46fa3c5b1a33..f0c5975edd0e 100644 --- a/tests/ovs-vsctl.at +++ b/tests/ovs-vsctl.at @@ -805,6 +805,20 @@ AT_CHECK( [RUN_OVS_VSCTL([--if-exists remove netflow x targets '"1.2.3.4:567"'])]) AT_CHECK( [RUN_OVS_VSCTL([--if-exists clear netflow x targets])]) + +AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 -- set Open_vSwitch . datapaths:"netdev"=@m])], [0], [stdout]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdev zone=1 icmp_first=1 icmp_reply=2])]) +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-zone-tp netdev zone=1 icmp_first=1 icmp_reply=2])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:1, Timeout Policies: icmp_first=1 icmp_reply=2 +]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdev zone=2 icmp_first=2 icmp_reply=3])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:1, Timeout Policies: icmp_first=1 icmp_reply=2 +Zone:2, Timeout Policies: icmp_first=2 icmp_reply=3 +]) +AT_CHECK([RUN_OVS_VSCTL([del-zone-tp netdev zone=1])]) +AT_CHECK([RUN_OVS_VSCTL([--if-exists del-zone-tp netdev zone=1])]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:2, Timeout Policies: icmp_first=2 icmp_reply=3 +]) OVS_VSCTL_CLEANUP AT_CLEANUP @@ -890,10 +904,10 @@ AT_CHECK([RUN_OVS_VSCTL([set bridge br0 flood_vlans=-1])], AT_CHECK([RUN_OVS_VSCTL([set bridge br0 flood_vlans=4096])], [1], [], [ovs-vsctl: constraint violation: 4096 is not in the valid range 0 to 4095 (inclusive) ]) -AT_CHECK([RUN_OVS_VSCTL([set c br1 'connection-mode=xyz'])], +AT_CHECK([RUN_OVS_VSCTL([set controller br1 'connection-mode=xyz'])], [1], [], [[ovs-vsctl: constraint violation: xyz is not one of the allowed values ([in-band, out-of-band]) ]]) -AT_CHECK([RUN_OVS_VSCTL([set c br1 connection-mode:x=y])], +AT_CHECK([RUN_OVS_VSCTL([set controller br1 connection-mode:x=y])], [1], [], [ovs-vsctl: cannot specify key to set for non-map column connection_mode ]) AT_CHECK([RUN_OVS_VSCTL([add bridge br1 datapath_id x y])], @@ -929,6 +943,22 @@ AT_CHECK([RUN_OVS_VSCTL([remove bridge br1 flood-vlans true])], AT_CHECK([RUN_OVS_VSCTL([clear bridge br1 name])], [1], [], [ovs-vsctl: cannot modify read-only column name in table Bridge ]) + +AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 -- set Open_vSwitch . datapaths:"netdev"=@m])], [0], [stdout]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdevxx zone=1 icmp_first=1 icmp_reply=2])], + [1], [], [ovs-vsctl: datapath: netdevxx record not found +]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdev zone=2 icmp_first=2 icmp_reply=3])]) +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdev zone=2 icmp_first=2 icmp_reply=3])], + [1], [], [ovs-vsctl: zone id 2 alread exists +]) +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([del-zone-tp netdev zone=11])], + [1], [], [ovs-vsctl: zone id 11 not exists. +]) +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:2, Timeout Policies: icmp_first=2 icmp_reply=3 +]) OVS_VSCTL_CLEANUP AT_CLEANUP diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in index 7c09df79bd29..0925d4d97b39 100644 --- a/utilities/ovs-vsctl.8.in +++ b/utilities/ovs-vsctl.8.in @@ -353,6 +353,31 @@ list. 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. +. +.IP "\fBadd\-zone\-tp \fIdatapath \fBzone=\fIzone_id \fIpolicies\fR" +Creates a conntrack zone with \fIzone_id\fR under the datapath \fIdatapath\fR. +Associate the conntrack timeout policies to it by a list of +\fIkey\fB=\fIvalue\fR pairs, separeted by space. For example, specifying +30-second timeout policy for first icmp packet, and 60-second for icmp reply packet +by doing \fBicmp_first=30 icmp_reply=60\fR. See CT_Timeout_Policy TABLE +at \fBovs-vswitchd.conf.db\fR(5) for all available configurations. +.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 does nothing if \fIzone_id\fR is already created\fR. +. +.IP "\fBdel\-zone\-tp \fIdatapath \fBzone=\fIzone_id\fR" +Delete a zone under \fIdatapath\fR by specifying its zone ID. +.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\-tp \fIdatapath\fR" +Prints the timeout policies of all zones under the \fIdatapath\fR. +. .SS "OpenFlow Controller Connectivity" . \fBovs\-vswitchd\fR can perform all configured bridging and switching diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index 4948137efe8c..16578edfc331 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -40,6 +40,7 @@ #include "ovsdb-idl.h" #include "openvswitch/poll-loop.h" #include "process.h" +#include "simap.h" #include "stream.h" #include "stream-ssl.h" #include "smap.h" @@ -49,6 +50,7 @@ #include "table.h" #include "timeval.h" #include "util.h" +#include "openvswitch/ofp-parse.h" #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" @@ -1153,6 +1155,201 @@ cmd_emer_reset(struct ctl_context *ctx) vsctl_context_invalidate_cache(ctx); } +static struct ovsrec_datapath * +find_datapath(struct vsctl_context *vsctl_ctx, const char *dp_name) +{ + const struct ovsrec_open_vswitch *ovs = vsctl_ctx->ovs; + int i; + + for (i = 0; i < ovs->n_datapaths; i++) { + if (!strcmp(ovs->key_datapaths[i], dp_name)) { + return ovs->value_datapaths[i]; + } + } + return NULL; +} + +static struct ovsrec_ct_zone * +find_ct_zone(struct ovsrec_datapath *dp, const int64_t zone_id) +{ + int i; + + for (i = 0; i < dp->n_ct_zones; i++) { + if (dp->key_ct_zones[i] == zone_id) { + return dp->value_ct_zones[i]; + } + } + return NULL; +} + +static struct ovsrec_ct_timeout_policy * +create_timeout_policy(struct ctl_context *ctx, char **argv, int n_tps) +{ + const struct ovsrec_ct_timeout_policy_table *tp_table; + const struct ovsrec_ct_timeout_policy *row; + struct ovsrec_ct_timeout_policy *tp = NULL; + const char **key_timeouts; + int64_t *value_timeouts; + struct simap new_tp, s; + int i, j; + + simap_init(&new_tp); + + key_timeouts = xmalloc(sizeof *key_timeouts * n_tps); + value_timeouts = xmalloc(sizeof *value_timeouts * n_tps); + + /* Parse timeout arguments. */ + for (i = 0; i < n_tps; i++) { + char *key, *value, *pos, *copy; + + pos = copy = xstrdup(argv[i]); + if (!ofputil_parse_key_value(&pos, &key, &value)) { + goto done; + } + key_timeouts[i] = key; + value_timeouts[i] = atoi(value); + simap_put(&new_tp, key, (unsigned int)value_timeouts[i]); + } +done: + + tp_table = ovsrec_ct_timeout_policy_table_get(ctx->idl); + OVSREC_CT_TIMEOUT_POLICY_TABLE_FOR_EACH (row, tp_table) { + simap_init(&s); + /* Covert to simap. */ + for (j = 0; j < row->n_timeouts; j++) { + simap_put(&s, row->key_timeouts[j], row->value_timeouts[j]); + } + + if (simap_equal(&s, &new_tp)) { + tp = CONST_CAST(struct ovsrec_ct_timeout_policy *, row); + simap_destroy(&s); + break; + } + simap_destroy(&s); + } + + if (!tp) { + tp = ovsrec_ct_timeout_policy_insert(ctx->txn); + ovsrec_ct_timeout_policy_set_timeouts(tp, key_timeouts, + (const int64_t *)value_timeouts, + n_tps); + } + + free(key_timeouts); + free(value_timeouts); + return tp; +} + +static void +cmd_add_zone(struct ctl_context *ctx) +{ + struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx); + struct ovsrec_ct_timeout_policy *tp; + struct ovsrec_ct_zone *zone; + struct ovsrec_datapath *dp; + const char *dp_name; + int64_t zone_id; + bool may_exist; + int n_tps; + + dp_name = ctx->argv[1]; + ovs_scan(ctx->argv[2], "zone=%"SCNi64, &zone_id); + may_exist = shash_find(&ctx->options, "--may-exist") != NULL; + + dp = find_datapath(vsctl_ctx, dp_name); + if (!dp) { + ctl_fatal("datapath: %s record not found", dp_name); + return; + } + + n_tps = ctx->argc - 3; + tp = create_timeout_policy(ctx, &ctx->argv[3], n_tps); + + zone = find_ct_zone(dp, zone_id); + if (zone) { + if (!may_exist) { + ctl_fatal("zone id %"PRIu64" alread exists", zone_id); + return; + } + ovsrec_ct_zone_set_timeout_policy(zone, tp); + } else { + zone = ovsrec_ct_zone_insert(ctx->txn); + ovsrec_ct_zone_set_timeout_policy(zone, tp); + ovsrec_datapath_update_ct_zones_setkey(dp, zone_id, zone); + } +} + +static void +cmd_del_zone(struct ctl_context *ctx) +{ + struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx); + struct ovsrec_ct_zone *zone; + struct ovsrec_datapath *dp; + const char *dp_name; + int64_t zone_id; + bool must_exist; + + must_exist = !shash_find(&ctx->options, "--if-exists"); + dp_name = ctx->argv[1]; + ovs_scan(ctx->argv[2], "zone=%"SCNi64, &zone_id); + + dp = find_datapath(vsctl_ctx, dp_name); + if (!dp) { + ctl_fatal("datapath: %s record not found.", dp_name); + return; + } + + zone = find_ct_zone(dp, zone_id); + if (must_exist && !zone) { + ctl_fatal("zone id %"PRIu64" not exists.", zone_id); + return; + } + + if (zone) { + ovsrec_datapath_update_ct_zones_delkey(dp, zone_id); + } +} + +static void +cmd_list_zone(struct ctl_context *ctx) +{ + struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx); + struct ovsrec_ct_timeout_policy *tp; + struct ovsrec_ct_zone *zone; + struct ovsrec_datapath *dp; + int i, j; + + dp = find_datapath(vsctl_ctx, ctx->argv[1]); + if (!dp) { + ctl_fatal("datapath: %s record not found", ctx->argv[1]); + return; + } + + for (i = 0; i < dp->n_ct_zones; i++) { + zone = dp->value_ct_zones[i]; + ds_put_format(&ctx->output, "Zone:%"PRIu64", Timeout Policies: ", + dp->key_ct_zones[i]); + + tp = zone->timeout_policy; + + for (j = 0; j < tp->n_timeouts - 1; j++) { + ds_put_format(&ctx->output, "%s=%"PRIu64" ", + tp->key_timeouts[j], tp->value_timeouts[j]); + } + ds_put_format(&ctx->output, "%s=%"PRIu64"\n", + tp->key_timeouts[j], tp->value_timeouts[j]); + } +} + +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_timeout_policy_col_timeouts); +} + static void cmd_add_br(struct ctl_context *ctx) { @@ -2896,6 +3093,13 @@ static const struct ctl_command_syntax vsctl_commands[] = { /* Switch commands. */ {"emer-reset", 0, 0, "", pre_cmd_emer_reset, cmd_emer_reset, NULL, "", RW}, + /* Zone and CT Timeout Policy commands. */ + {"add-zone-tp", 2, 19, "", pre_get_zone, cmd_add_zone, NULL, + "--may-exist", RW}, + {"del-zone-tp", 2, 2, "", pre_get_zone, cmd_del_zone, NULL, + "--if-exists", RW}, + {"list-zone-tp", 1, 1, "", pre_get_zone, cmd_list_zone, NULL, "", RO}, + {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO}, }; From patchwork Thu Aug 1 22:07:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 1140790 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="M8P5ztHp"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4604GL19Ykz9s3Z for ; Fri, 2 Aug 2019 08:09:46 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id A176715F3; Thu, 1 Aug 2019 22:07:47 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id E58A215B7 for ; Thu, 1 Aug 2019 22:07:46 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 638A982B for ; Thu, 1 Aug 2019 22:07:46 +0000 (UTC) Received: by mail-wm1-f48.google.com with SMTP id l2so64471491wmg.0 for ; Thu, 01 Aug 2019 15:07:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=CLvRfEJLK+R/d2A5MjDQFGy38dq5RtREraKsTjaKB34=; b=M8P5ztHpqVln6eA4qGVfhFSZmuP4pkLUqOzu+q59yq3eD+9Wlp7a48PyDJNUTAYD/Y pSPNq6A6WbbN8eUdFg7r537vxi8Kxx+d1EznhvuVhqHLT94Mqom97b4gwTnV2CoMVM2R zDNraWuObc4vaJ0yBM+lkg+Nghtl4nO2mMg0aw1gYt7ilIlyPL6n5UVo8bkepDO3ikuE lM+8OSZD3EBx5aaoNW1STNzDtsuW/8FaJgGKugdXpWHow4Z29PIdcFzTR956KtZ61QDS /y6pbXjUTTwMb/I9u/we/RmGH/gsXlB0TV+njTYXzoxxm7AeZMoki+QcQCyhqKzxwY8q vo9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=CLvRfEJLK+R/d2A5MjDQFGy38dq5RtREraKsTjaKB34=; b=P+x2G/uUVgrquuXMmBiL7Q/eLvmz5okuwOohBn59/zyEzCSzff0FDHFmv5nvYERkTd EVLHAt7R1m2mrGELM7ePjkVr8ACz1eOBzv49tCBfDtVSU4QV4LVuxp2ioOtOE9mM1RJu TxTjBnk0Jxmm4/yw33HECT9c8B3YZOp2sIS68MBGiOeemAYz9fvJFVTJHK6cu1hK4gFF JUTgobcHsOkktBzezR5tTToIIzwtRUD1lszFA495nJMOsHWcBQVvtPqOkq+1xdwX8ZBw nmJSvihPpXg8upcHZkFCLrB/wdawYv0XLjgRxl+yA/YBpBJU13wKfnXAmOBfazCSvpw2 zCAw== X-Gm-Message-State: APjAAAW9T1mKes0oWGk5QMP+8IqBE6h3cmhtxMoFHh2rCaIV9ghmNHYX haP8tlKLk9HG0WhEDrxAGQFOsfWz X-Google-Smtp-Source: APXvYqyYnv0+pORyMhcQ23jdx9wDRazy/5txefek2SU77MnHymF1sWhbmjoCTIGTBgzg/B/ADgs8dw== X-Received: by 2002:a1c:3883:: with SMTP id f125mr556119wma.18.1564697264710; Thu, 01 Aug 2019 15:07:44 -0700 (PDT) Received: from vm-main.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id z19sm54128982wmi.7.2019.08.01.15.07.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Aug 2019 15:07:43 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Thu, 1 Aug 2019 15:07:27 -0700 Message-Id: <1564697253-37992-4-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> References: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 3/9] ct-dpif: Export ct_dpif_format_ipproto() X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This function will be useful for following patchs. Signed-off-by: Yi-Hung Wei Acked-by: Justin Pettit --- lib/ct-dpif.c | 3 +-- lib/ct-dpif.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c index 5d8a75d3a63f..6ea7feb0ee35 100644 --- a/lib/ct-dpif.c +++ b/lib/ct-dpif.c @@ -31,7 +31,6 @@ struct flags { const char *name; }; -static void ct_dpif_format_ipproto(struct ds *, uint16_t ipproto); static void ct_dpif_format_counters(struct ds *, const struct ct_dpif_counters *); static void ct_dpif_format_timestamp(struct ds *, @@ -315,7 +314,7 @@ ct_dpif_format_entry(const struct ct_dpif_entry *entry, struct ds *ds, } } -static void +void ct_dpif_format_ipproto(struct ds *ds, uint16_t ipproto) { const char *name; diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h index 14178bb7c3f0..2f4906817946 100644 --- a/lib/ct-dpif.h +++ b/lib/ct-dpif.h @@ -250,6 +250,7 @@ int ct_dpif_ipf_dump_done(struct dpif *dpif, void *); void ct_dpif_entry_uninit(struct ct_dpif_entry *); void ct_dpif_format_entry(const struct ct_dpif_entry *, struct ds *, bool verbose, bool print_stats); +void ct_dpif_format_ipproto(struct ds *ds, uint16_t ipproto); void ct_dpif_format_tuple(struct ds *, const struct ct_dpif_tuple *); uint8_t ct_dpif_coalesce_tcp_state(uint8_t state); void ct_dpif_format_tcp_stat(struct ds *, int, int); From patchwork Thu Aug 1 22:07:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 1140792 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="B3YjeZgc"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4604HQ2kdTz9s3Z for ; Fri, 2 Aug 2019 08:10:42 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 1F1421683; Thu, 1 Aug 2019 22:07:54 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 15C351661 for ; Thu, 1 Aug 2019 22:07:53 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 7A6CF8A0 for ; Thu, 1 Aug 2019 22:07:49 +0000 (UTC) Received: by mail-wm1-f45.google.com with SMTP id p74so66019889wme.4 for ; Thu, 01 Aug 2019 15:07:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7OqmhQZYRem4LYwLsRBfbhBWPFAl2Fg3Wql/I8cEUQs=; b=B3YjeZgcM8ZDd6dNrapW6HbFKxzWJXuT29xzUCDGrwEKFNDSjg8tcwmeTaEES5Eumd uU+S5NBO73RQaokPRWSofGjVy+Op648rCq8/3IeU105dvcbBw8BuDj2wmwaxD2uTsftO wds64ilcBnTdiGKnrGCg6z5JlH75UalJDR5b5nKc/i0JrWVVwTaON/c5NDgRUcHRm3pA /XQruBqqO7sExyIW7vj/N8XaVV+FVzcIgzUnpWzkQnHCXJApnDmm+s+3gyvudGiQk2mq Tsfd53JYxzhZsp+PN0lGqF97023FAU2n0th2vV7w8sj0GPFNitjoPV6XrM8ob0uK+T41 DLGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7OqmhQZYRem4LYwLsRBfbhBWPFAl2Fg3Wql/I8cEUQs=; b=ht+3KtJB2X643Bbiqo3VuTyndwoypmhzi9XvGrZHNvEU2mhiZulSuX6srbVkVF2djG +fGJFWJlLSRyTuNPAsz4Fl//SQrsxzIljWPpQ1eszFRF9pdy/yFqzqQGv7TVDazYZKT6 MF2JRWSGXyG+G5h/1F5Rvc11hlsXHKJoGaSgfY1rUqiqDwjXqWQPxzRfXv88DciEn9Gf JxfokH6XIEIZSFF7zLwJ0v8I5z/+vlpREzjep6ofqGeiFtnlNFUWqFdTyHtrU3TTmmhp 7jI/ORPDY2Pgjdux4pCCJqzjkfnpVl0B7d77mjI1LMw78wTx1pdNxS96f3UZHwf92Kbi jglA== X-Gm-Message-State: APjAAAX2ohvdajXcPqyC/U4YaEUrGqJIqsfNaJRO3lNDulYzIpcHt1oE 93LHhjvux5G9zMxez0sK5kYwC899 X-Google-Smtp-Source: APXvYqx3N2tEIDjpCHgMFZ14P/gTm8sd1X50iDv5x6jBiyzzn57FKCh0omZFFDUufQbgpH7irPae/g== X-Received: by 2002:a7b:cbcb:: with SMTP id n11mr552884wmi.54.1564697267096; Thu, 01 Aug 2019 15:07:47 -0700 (PDT) Received: from vm-main.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id z19sm54128982wmi.7.2019.08.01.15.07.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Aug 2019 15:07:46 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Thu, 1 Aug 2019 15:07:28 -0700 Message-Id: <1564697253-37992-5-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> References: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 4/9] ct-dpif, dpif-netlink: Add conntrack timeout policy support X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch first defines the dpif interface for a datapath to support adding, deleting, getting and dumping conntrack timeout policy. The timeout policy is identified by a 4 bytes unsigned integer in datapath, and it currently support timeout for TCP, UDP, and ICMP protocols. Moreover, this patch provides the implemetation for Linux kernel datapath in dpif-netlink. In Linux kernel, the timeout policy is maintained per L3/L4 protocol, and it is identified by 32 bytes null terminated string. On the other hand, in vswitchd, the timeout policy is a generic one that consists of all the supported L4 protocols. Therefore, one of the main task in dpif-netlink is to break down the generic timeout policy into 6 sub policies (ipv4 tcp, udp, icmp, and ipv6 tcp, udp, icmp), and push down the configuration using the netlink API in netlink-conntrack.c. This patch also adds missing symbols in the windows datapath so that the build on windows can pass. Appveyor CI: * https://ci.appveyor.com/project/YiHungWei/ovs/builds/26387754 Signed-off-by: Yi-Hung Wei --- datapath-windows/include/OvsDpInterfaceCtExt.h | 114 +++++ datapath-windows/ovsext/Netlink/NetlinkProto.h | 1 + include/windows/automake.mk | 1 + .../windows/linux/netfilter/nfnetlink_cttimeout.h | 0 lib/ct-dpif.c | 104 +++++ lib/ct-dpif.h | 56 +++ lib/dpif-netdev.c | 6 + lib/dpif-netlink.c | 462 +++++++++++++++++++++ lib/dpif-netlink.h | 1 + lib/dpif-provider.h | 38 ++ lib/netlink-conntrack.c | 363 ++++++++++++++++ lib/netlink-conntrack.h | 29 ++ lib/netlink-protocol.h | 1 + 13 files changed, 1176 insertions(+) create mode 100644 include/windows/linux/netfilter/nfnetlink_cttimeout.h diff --git a/datapath-windows/include/OvsDpInterfaceCtExt.h b/datapath-windows/include/OvsDpInterfaceCtExt.h index 3b947782e90c..4379855bb8dd 100644 --- a/datapath-windows/include/OvsDpInterfaceCtExt.h +++ b/datapath-windows/include/OvsDpInterfaceCtExt.h @@ -421,4 +421,118 @@ struct nf_ct_tcp_flags { UINT8 mask; }; +/* File: nfnetlink_cttimeout.h */ +enum ctnl_timeout_msg_types { + IPCTNL_MSG_TIMEOUT_NEW, + IPCTNL_MSG_TIMEOUT_GET, + IPCTNL_MSG_TIMEOUT_DELETE, + IPCTNL_MSG_TIMEOUT_DEFAULT_SET, + IPCTNL_MSG_TIMEOUT_DEFAULT_GET, + + IPCTNL_MSG_TIMEOUT_MAX +}; + +enum ctattr_timeout { + CTA_TIMEOUT_UNSPEC, + CTA_TIMEOUT_NAME, + CTA_TIMEOUT_L3PROTO, + CTA_TIMEOUT_L4PROTO, + CTA_TIMEOUT_DATA, + CTA_TIMEOUT_USE, + __CTA_TIMEOUT_MAX +}; +#define CTA_TIMEOUT_MAX (__CTA_TIMEOUT_MAX - 1) + +enum ctattr_timeout_generic { + CTA_TIMEOUT_GENERIC_UNSPEC, + CTA_TIMEOUT_GENERIC_TIMEOUT, + __CTA_TIMEOUT_GENERIC_MAX +}; +#define CTA_TIMEOUT_GENERIC_MAX (__CTA_TIMEOUT_GENERIC_MAX - 1) + +enum ctattr_timeout_tcp { + CTA_TIMEOUT_TCP_UNSPEC, + CTA_TIMEOUT_TCP_SYN_SENT, + CTA_TIMEOUT_TCP_SYN_RECV, + CTA_TIMEOUT_TCP_ESTABLISHED, + CTA_TIMEOUT_TCP_FIN_WAIT, + CTA_TIMEOUT_TCP_CLOSE_WAIT, + CTA_TIMEOUT_TCP_LAST_ACK, + CTA_TIMEOUT_TCP_TIME_WAIT, + CTA_TIMEOUT_TCP_CLOSE, + CTA_TIMEOUT_TCP_SYN_SENT2, + CTA_TIMEOUT_TCP_RETRANS, + CTA_TIMEOUT_TCP_UNACK, + __CTA_TIMEOUT_TCP_MAX +}; +#define CTA_TIMEOUT_TCP_MAX (__CTA_TIMEOUT_TCP_MAX - 1) + +enum ctattr_timeout_udp { + CTA_TIMEOUT_UDP_UNSPEC, + CTA_TIMEOUT_UDP_UNREPLIED, + CTA_TIMEOUT_UDP_REPLIED, + __CTA_TIMEOUT_UDP_MAX +}; +#define CTA_TIMEOUT_UDP_MAX (__CTA_TIMEOUT_UDP_MAX - 1) + +enum ctattr_timeout_udplite { + CTA_TIMEOUT_UDPLITE_UNSPEC, + CTA_TIMEOUT_UDPLITE_UNREPLIED, + CTA_TIMEOUT_UDPLITE_REPLIED, + __CTA_TIMEOUT_UDPLITE_MAX +}; +#define CTA_TIMEOUT_UDPLITE_MAX (__CTA_TIMEOUT_UDPLITE_MAX - 1) + +enum ctattr_timeout_icmp { + CTA_TIMEOUT_ICMP_UNSPEC, + CTA_TIMEOUT_ICMP_TIMEOUT, + __CTA_TIMEOUT_ICMP_MAX +}; +#define CTA_TIMEOUT_ICMP_MAX (__CTA_TIMEOUT_ICMP_MAX - 1) + +enum ctattr_timeout_dccp { + CTA_TIMEOUT_DCCP_UNSPEC, + CTA_TIMEOUT_DCCP_REQUEST, + CTA_TIMEOUT_DCCP_RESPOND, + CTA_TIMEOUT_DCCP_PARTOPEN, + CTA_TIMEOUT_DCCP_OPEN, + CTA_TIMEOUT_DCCP_CLOSEREQ, + CTA_TIMEOUT_DCCP_CLOSING, + CTA_TIMEOUT_DCCP_TIMEWAIT, + __CTA_TIMEOUT_DCCP_MAX +}; +#define CTA_TIMEOUT_DCCP_MAX (__CTA_TIMEOUT_DCCP_MAX - 1) + +enum ctattr_timeout_sctp { + CTA_TIMEOUT_SCTP_UNSPEC, + CTA_TIMEOUT_SCTP_CLOSED, + CTA_TIMEOUT_SCTP_COOKIE_WAIT, + CTA_TIMEOUT_SCTP_COOKIE_ECHOED, + CTA_TIMEOUT_SCTP_ESTABLISHED, + CTA_TIMEOUT_SCTP_SHUTDOWN_SENT, + CTA_TIMEOUT_SCTP_SHUTDOWN_RECD, + CTA_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT, + CTA_TIMEOUT_SCTP_HEARTBEAT_SENT, + CTA_TIMEOUT_SCTP_HEARTBEAT_ACKED, + __CTA_TIMEOUT_SCTP_MAX +}; +#define CTA_TIMEOUT_SCTP_MAX (__CTA_TIMEOUT_SCTP_MAX - 1) + +enum ctattr_timeout_icmpv6 { + CTA_TIMEOUT_ICMPV6_UNSPEC, + CTA_TIMEOUT_ICMPV6_TIMEOUT, + __CTA_TIMEOUT_ICMPV6_MAX +}; +#define CTA_TIMEOUT_ICMPV6_MAX (__CTA_TIMEOUT_ICMPV6_MAX - 1) + +enum ctattr_timeout_gre { + CTA_TIMEOUT_GRE_UNSPEC, + CTA_TIMEOUT_GRE_UNREPLIED, + CTA_TIMEOUT_GRE_REPLIED, + __CTA_TIMEOUT_GRE_MAX +}; +#define CTA_TIMEOUT_GRE_MAX (__CTA_TIMEOUT_GRE_MAX - 1) + +#define CTNL_TIMEOUT_NAME_MAX 32 + #endif /* __OVS_DP_INTERFACE_CT_EXT_H_ */ diff --git a/datapath-windows/ovsext/Netlink/NetlinkProto.h b/datapath-windows/ovsext/Netlink/NetlinkProto.h index 59b56565c1dc..db1fa2bacae8 100644 --- a/datapath-windows/ovsext/Netlink/NetlinkProto.h +++ b/datapath-windows/ovsext/Netlink/NetlinkProto.h @@ -51,6 +51,7 @@ #define NLM_F_ECHO 0x008 #define NLM_F_ROOT 0x100 +#define NLM_F_REPLACE 0x100 #define NLM_F_MATCH 0x200 #define NLM_F_EXCL 0x200 #define NLM_F_ATOMIC 0x400 diff --git a/include/windows/automake.mk b/include/windows/automake.mk index 382627b51787..883bbbf5d97c 100644 --- a/include/windows/automake.mk +++ b/include/windows/automake.mk @@ -15,6 +15,7 @@ noinst_HEADERS += \ include/windows/linux/netfilter/nf_conntrack_tcp.h \ include/windows/linux/netfilter/nfnetlink.h \ include/windows/linux/netfilter/nfnetlink_conntrack.h \ + include/windows/linux/netfilter/nfnetlink_cttimeout.h \ include/windows/linux/pkt_sched.h \ include/windows/linux/types.h \ include/windows/net/if.h \ diff --git a/include/windows/linux/netfilter/nfnetlink_cttimeout.h b/include/windows/linux/netfilter/nfnetlink_cttimeout.h new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c index 6ea7feb0ee35..7f9ce0a561f7 100644 --- a/lib/ct-dpif.c +++ b/lib/ct-dpif.c @@ -760,3 +760,107 @@ ct_dpif_format_zone_limits(uint32_t default_limit, ds_put_format(ds, ",count=%"PRIu32, zone_limit->count); } } + +static const char *const ct_dpif_tp_attr_string[] = { +#define CT_DPIF_TP_TCP_ATTR(ATTR) \ + [CT_DPIF_TP_ATTR_TCP_##ATTR] = "TCP_"#ATTR, + CT_DPIF_TP_TCP_ATTRS +#undef CT_DPIF_TP_TCP_ATTR +#define CT_DPIF_TP_UDP_ATTR(ATTR) \ + [CT_DPIF_TP_ATTR_UDP_##ATTR] = "UDP_"#ATTR, + CT_DPIF_TP_UDP_ATTRS +#undef CT_DPIF_TP_UDP_ATTR +#define CT_DPIF_TP_ICMP_ATTR(ATTR) \ + [CT_DPIF_TP_ATTR_ICMP_##ATTR] = "ICMP_"#ATTR, + CT_DPIF_TP_ICMP_ATTRS +#undef CT_DPIF_TP_ICMP_ATTR +}; + +static bool +ct_dpif_set_timeout_policy_attr(struct ct_dpif_timeout_policy *tp, + uint32_t attr, uint32_t value) +{ + if (tp->present & (1 << attr) && tp->attrs[attr] == value) { + return false; + } + tp->attrs[attr] = value; + tp->present |= 1 << attr; + return true; +} + +/* Sets a timeout value identified by '*name' to 'value'. + * Returns true if the attribute is changed */ +bool +ct_dpif_set_timeout_policy_attr_by_name(struct ct_dpif_timeout_policy *tp, + const char *name, uint32_t value) +{ + uint32_t i; + + for (i = 0; i < CT_DPIF_TP_ATTR_MAX; ++i) { + if (!strcasecmp(name, ct_dpif_tp_attr_string[i])) { + return ct_dpif_set_timeout_policy_attr(tp, i, value); + } + } + return false; +} + +bool +ct_dpif_timeout_policy_support_ipproto(uint8_t ipproto) +{ + if (ipproto == IPPROTO_TCP || ipproto == IPPROTO_UDP || + ipproto == IPPROTO_ICMP || ipproto == IPPROTO_ICMPV6) { + return true; + } + return false; +} + +int +ct_dpif_set_timeout_policy(struct dpif *dpif, + const struct ct_dpif_timeout_policy *tp) +{ + return (dpif->dpif_class->ct_set_timeout_policy + ? dpif->dpif_class->ct_set_timeout_policy(dpif, tp) + : EOPNOTSUPP); +} + +int +ct_dpif_del_timeout_policy(struct dpif *dpif, uint32_t tp_id) +{ + return (dpif->dpif_class->ct_del_timeout_policy + ? dpif->dpif_class->ct_del_timeout_policy(dpif, tp_id) + : EOPNOTSUPP); +} + +int +ct_dpif_get_timeout_policy(struct dpif *dpif, uint32_t tp_id, + struct ct_dpif_timeout_policy *tp) +{ + return (dpif->dpif_class->ct_get_timeout_policy + ? dpif->dpif_class->ct_get_timeout_policy( + dpif, tp_id, tp) : EOPNOTSUPP); +} + +int +ct_dpif_timeout_policy_dump_start(struct dpif *dpif, void **statep) +{ + return (dpif->dpif_class->ct_timeout_policy_dump_start + ? dpif->dpif_class->ct_timeout_policy_dump_start(dpif, statep) + : EOPNOTSUPP); +} + +int +ct_dpif_timeout_policy_dump_next(struct dpif *dpif, void *state, + struct ct_dpif_timeout_policy *tp) +{ + return (dpif->dpif_class->ct_timeout_policy_dump_next + ? dpif->dpif_class->ct_timeout_policy_dump_next(dpif, state, tp) + : EOPNOTSUPP); +} + +int +ct_dpif_timeout_policy_dump_done(struct dpif *dpif, void *state) +{ + return (dpif->dpif_class->ct_timeout_policy_dump_done + ? dpif->dpif_class->ct_timeout_policy_dump_done(dpif, state) + : EOPNOTSUPP); +} diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h index 2f4906817946..8dacb1c7c253 100644 --- a/lib/ct-dpif.h +++ b/lib/ct-dpif.h @@ -225,6 +225,50 @@ struct ct_dpif_zone_limit { struct ovs_list node; }; +#define CT_DPIF_TP_TCP_ATTRS \ + CT_DPIF_TP_TCP_ATTR(SYN_SENT) \ + CT_DPIF_TP_TCP_ATTR(SYN_RECV) \ + CT_DPIF_TP_TCP_ATTR(ESTABLISHED) \ + CT_DPIF_TP_TCP_ATTR(FIN_WAIT) \ + CT_DPIF_TP_TCP_ATTR(CLOSE_WAIT) \ + CT_DPIF_TP_TCP_ATTR(LAST_ACK) \ + CT_DPIF_TP_TCP_ATTR(TIME_WAIT) \ + CT_DPIF_TP_TCP_ATTR(CLOSE) \ + CT_DPIF_TP_TCP_ATTR(SYN_SENT2) \ + CT_DPIF_TP_TCP_ATTR(RETRANSMIT) \ + CT_DPIF_TP_TCP_ATTR(UNACK) + +#define CT_DPIF_TP_UDP_ATTRS \ + CT_DPIF_TP_UDP_ATTR(FIRST) \ + CT_DPIF_TP_UDP_ATTR(SINGLE) \ + CT_DPIF_TP_UDP_ATTR(MULTIPLE) + +#define CT_DPIF_TP_ICMP_ATTRS \ + CT_DPIF_TP_ICMP_ATTR(FIRST) \ + CT_DPIF_TP_ICMP_ATTR(REPLY) + +enum OVS_PACKED_ENUM ct_dpif_tp_attr { +#define CT_DPIF_TP_TCP_ATTR(ATTR) CT_DPIF_TP_ATTR_TCP_##ATTR, + CT_DPIF_TP_TCP_ATTRS +#undef CT_DPIF_TP_TCP_ATTR +#define CT_DPIF_TP_UDP_ATTR(ATTR) CT_DPIF_TP_ATTR_UDP_##ATTR, + CT_DPIF_TP_UDP_ATTRS +#undef CT_DPIF_TP_UDP_ATTR +#define CT_DPIF_TP_ICMP_ATTR(ATTR) CT_DPIF_TP_ATTR_ICMP_##ATTR, + CT_DPIF_TP_ICMP_ATTRS +#undef CT_DPIF_TP_ICMP_ATTR + CT_DPIF_TP_ATTR_MAX +}; + +struct ct_dpif_timeout_policy { + uint32_t id; /* An unique identifier of a timeout policy in + * the datapath. */ + uint32_t present; /* If a timeout attribute is present set the + * corresponding bit. */ + uint32_t attrs[CT_DPIF_TP_ATTR_MAX]; /* An array that specifies + * timeout attribute values */ +}; + int ct_dpif_dump_start(struct dpif *, struct ct_dpif_dump_state **, const uint16_t *zone, int *); int ct_dpif_dump_next(struct ct_dpif_dump_state *, struct ct_dpif_entry *); @@ -262,5 +306,17 @@ bool ct_dpif_parse_zone_limit_tuple(const char *s, uint16_t *pzone, uint32_t *plimit, struct ds *); void ct_dpif_format_zone_limits(uint32_t default_limit, const struct ovs_list *, struct ds *); +bool ct_dpif_set_timeout_policy_attr_by_name(struct ct_dpif_timeout_policy *tp, + const char *key, uint32_t value); +bool ct_dpif_timeout_policy_support_ipproto(uint8_t ipproto); +int ct_dpif_set_timeout_policy(struct dpif *dpif, + const struct ct_dpif_timeout_policy *tp); +int ct_dpif_get_timeout_policy(struct dpif *dpif, uint32_t tp_id, + struct ct_dpif_timeout_policy *tp); +int ct_dpif_del_timeout_policy(struct dpif *dpif, uint32_t tp_id); +int ct_dpif_timeout_policy_dump_start(struct dpif *dpif, void **statep); +int ct_dpif_timeout_policy_dump_next(struct dpif *dpif, void *state, + struct ct_dpif_timeout_policy *tp); +int ct_dpif_timeout_policy_dump_done(struct dpif *dpif, void *state); #endif /* CT_DPIF_H */ diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index d0a1c58adace..2079e368fb52 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -7529,6 +7529,12 @@ const struct dpif_class dpif_netdev_class = { NULL, /* ct_set_limits */ NULL, /* ct_get_limits */ NULL, /* ct_del_limits */ + NULL, /* ct_set_timeout_policy */ + NULL, /* ct_get_timeout_policy */ + NULL, /* ct_del_timeout_policy */ + NULL, /* ct_timeout_policy_dump_start */ + NULL, /* ct_timeout_policy_dump_next */ + NULL, /* ct_timeout_policy_dump_done */ dpif_netdev_ipf_set_enabled, dpif_netdev_ipf_set_min_frag, dpif_netdev_ipf_set_max_nfrags, diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 7bc71d6d19d7..b859508f718a 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -50,6 +50,7 @@ #include "odp-util.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/flow.h" +#include "openvswitch/hmap.h" #include "openvswitch/match.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/poll-loop.h" @@ -3023,6 +3024,461 @@ dpif_netlink_ct_del_limits(struct dpif *dpif OVS_UNUSED, ofpbuf_delete(request); return err; } + +#define NL_TP_NAME_PREFIX "ovs_tp_" + +struct dpif_netlink_timeout_policy_protocol { + uint16_t l3num; + uint8_t l4num; +}; + +enum OVS_PACKED_ENUM dpif_netlink_support_timeout_policy_protocol { + DPIF_NL_TP_AF_INET_TCP, + DPIF_NL_TP_AF_INET_UDP, + DPIF_NL_TP_AF_INET_ICMP, + DPIF_NL_TP_AF_INET6_TCP, + DPIF_NL_TP_AF_INET6_UDP, + DPIF_NL_TP_AF_INET6_ICMPV6, + DPIF_NL_TP_MAX +}; + +#define DPIF_NL_ALL_TP 0x3F + +static struct dpif_netlink_timeout_policy_protocol tp_protos[] = { + [DPIF_NL_TP_AF_INET_TCP] = { .l3num = AF_INET, .l4num = IPPROTO_TCP }, + [DPIF_NL_TP_AF_INET_UDP] = { .l3num = AF_INET, .l4num = IPPROTO_UDP }, + [DPIF_NL_TP_AF_INET_ICMP] = { .l3num = AF_INET, .l4num = IPPROTO_ICMP }, + [DPIF_NL_TP_AF_INET6_TCP] = { .l3num = AF_INET6, .l4num = IPPROTO_TCP }, + [DPIF_NL_TP_AF_INET6_UDP] = { .l3num = AF_INET6, .l4num = IPPROTO_UDP }, + [DPIF_NL_TP_AF_INET6_ICMPV6] = { .l3num = AF_INET6, + .l4num = IPPROTO_ICMPV6 }, +}; + +static void +dpif_netlink_format_tp_name(uint32_t id, uint16_t l3num, uint8_t l4num, + struct ds *tp_name) +{ + ds_clear(tp_name); + ds_put_format(tp_name, "%s%"PRIu32"_", NL_TP_NAME_PREFIX, id); + ct_dpif_format_ipproto(tp_name, l4num); + + if (l3num == AF_INET) { + ds_put_cstr(tp_name, "4"); + } else if (l3num == AF_INET6 && l4num != IPPROTO_ICMPV6) { + ds_put_cstr(tp_name, "6"); + } + + ovs_assert(tp_name->length < CTNL_TIMEOUT_NAME_MAX); +} + +#define CT_DPIF_NL_TP_TCP_MAPPINGS \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, SYN_SENT, SYN_SENT) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, SYN_RECV, SYN_RECV) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, ESTABLISHED, ESTABLISHED) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, FIN_WAIT, FIN_WAIT) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, CLOSE_WAIT, CLOSE_WAIT) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, LAST_ACK, LAST_ACK) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, TIME_WAIT, TIME_WAIT) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, CLOSE, CLOSE) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, SYN_SENT2, SYN_SENT2) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, RETRANSMIT, RETRANS) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, UNACK, UNACK) + +#define CT_DPIF_NL_TP_UDP_MAPPINGS \ + CT_DPIF_NL_TP_MAPPING(UDP, UDP, SINGLE, UNREPLIED) \ + CT_DPIF_NL_TP_MAPPING(UDP, UDP, MULTIPLE, REPLIED) + +#define CT_DPIF_NL_TP_ICMP_MAPPINGS \ + CT_DPIF_NL_TP_MAPPING(ICMP, ICMP, FIRST, TIMEOUT) + +#define CT_DPIF_NL_TP_ICMPV6_MAPPINGS \ + CT_DPIF_NL_TP_MAPPING(ICMP, ICMPV6, FIRST, TIMEOUT) + + +#define CT_DPIF_NL_TP_MAPPING(PROTO1, PROTO2, ATTR1, ATTR2) \ +if (tp->present & (1 << CT_DPIF_TP_ATTR_##PROTO1##_##ATTR1)) { \ + nl_tp->present |= 1 << CTA_TIMEOUT_##PROTO2##_##ATTR2; \ + nl_tp->attrs[CTA_TIMEOUT_##PROTO2##_##ATTR2] = \ + tp->attrs[CT_DPIF_TP_ATTR_##PROTO1##_##ATTR1]; \ +} + +static void +dpif_netlink_get_nl_tp_tcp_attrs(const struct ct_dpif_timeout_policy *tp, + struct nl_ct_timeout_policy *nl_tp) +{ + CT_DPIF_NL_TP_TCP_MAPPINGS +} + +static void +dpif_netlink_get_nl_tp_udp_attrs(const struct ct_dpif_timeout_policy *tp, + struct nl_ct_timeout_policy *nl_tp) +{ + CT_DPIF_NL_TP_UDP_MAPPINGS +} + +static void +dpif_netlink_get_nl_tp_icmp_attrs(const struct ct_dpif_timeout_policy *tp, + struct nl_ct_timeout_policy *nl_tp) +{ + CT_DPIF_NL_TP_ICMP_MAPPINGS +} + +static void +dpif_netlink_get_nl_tp_icmpv6_attrs(const struct ct_dpif_timeout_policy *tp, + struct nl_ct_timeout_policy *nl_tp) +{ + CT_DPIF_NL_TP_ICMPV6_MAPPINGS +} + +#undef CT_DPIF_NL_TP_MAPPING + +static void +dpif_netlink_get_nl_tp_attrs(const struct ct_dpif_timeout_policy *tp, + uint8_t l4num, struct nl_ct_timeout_policy *nl_tp) +{ + nl_tp->present = 0; + + if (l4num == IPPROTO_TCP) { + dpif_netlink_get_nl_tp_tcp_attrs(tp, nl_tp); + } else if (l4num == IPPROTO_UDP) { + dpif_netlink_get_nl_tp_udp_attrs(tp, nl_tp); + } else if (l4num == IPPROTO_ICMP) { + dpif_netlink_get_nl_tp_icmp_attrs(tp, nl_tp); + } else if (l4num == IPPROTO_ICMPV6) { + dpif_netlink_get_nl_tp_icmpv6_attrs(tp, nl_tp); + } +} + +#define CT_DPIF_NL_TP_MAPPING(PROTO1, PROTO2, ATTR1, ATTR2) \ +if (nl_tp->present & (1 << CTA_TIMEOUT_##PROTO2##_##ATTR2)) { \ + if (tp->present & (1 << CT_DPIF_TP_ATTR_##PROTO1##_##ATTR1)) { \ + if (tp->attrs[CT_DPIF_TP_ATTR_##PROTO1##_##ATTR1] != \ + nl_tp->attrs[CTA_TIMEOUT_##PROTO2##_##ATTR2]) { \ + VLOG_WARN_RL(&error_rl, "Inconsistent timeout policy %s " \ + "attribute %s=%"PRIu32" while %s=%"PRIu32, \ + nl_tp->name, "CTA_TIMEOUT_"#PROTO2"_"#ATTR2, \ + nl_tp->attrs[CTA_TIMEOUT_##PROTO2##_##ATTR2], \ + "CT_DPIF_TP_ATTR_"#PROTO1"_"#ATTR1, \ + tp->attrs[CT_DPIF_TP_ATTR_##PROTO1##_##ATTR1]); \ + } \ + } else { \ + tp->present |= 1 << CT_DPIF_TP_ATTR_##PROTO1##_##ATTR1; \ + tp->attrs[CT_DPIF_TP_ATTR_##PROTO1##_##ATTR1] = \ + nl_tp->attrs[CTA_TIMEOUT_##PROTO2##_##ATTR2]; \ + } \ +} + +static void +dpif_netlink_set_ct_dpif_tp_tcp_attrs(const struct nl_ct_timeout_policy *nl_tp, + struct ct_dpif_timeout_policy *tp) +{ + CT_DPIF_NL_TP_TCP_MAPPINGS +} + +static void +dpif_netlink_set_ct_dpif_tp_udp_attrs(const struct nl_ct_timeout_policy *nl_tp, + struct ct_dpif_timeout_policy *tp) +{ + CT_DPIF_NL_TP_UDP_MAPPINGS +} + +static void +dpif_netlink_set_ct_dpif_tp_icmp_attrs( + const struct nl_ct_timeout_policy *nl_tp, + struct ct_dpif_timeout_policy *tp) +{ + CT_DPIF_NL_TP_ICMP_MAPPINGS +} + +static void +dpif_netlink_set_ct_dpif_tp_icmpv6_attrs( + const struct nl_ct_timeout_policy *nl_tp, + struct ct_dpif_timeout_policy *tp) +{ + CT_DPIF_NL_TP_ICMPV6_MAPPINGS +} + +#undef CT_DPIF_NL_TP_MAPPING + +static void +dpif_netlink_set_ct_dpif_tp_attrs(const struct nl_ct_timeout_policy *nl_tp, + struct ct_dpif_timeout_policy *tp) +{ + if (nl_tp->l4num == IPPROTO_TCP) { + dpif_netlink_set_ct_dpif_tp_tcp_attrs(nl_tp, tp); + } else if (nl_tp->l4num == IPPROTO_UDP) { + dpif_netlink_set_ct_dpif_tp_udp_attrs(nl_tp, tp); + } else if (nl_tp->l4num == IPPROTO_ICMP) { + dpif_netlink_set_ct_dpif_tp_icmp_attrs(nl_tp, tp); + } else if (nl_tp->l4num == IPPROTO_ICMPV6) { + dpif_netlink_set_ct_dpif_tp_icmpv6_attrs(nl_tp, tp); + } +} + +#ifdef _WIN32 +static int +dpif_netlink_ct_set_timeout_policy(struct dpif *dpif OVS_UNUSED, + const struct ct_dpif_timeout_policy *tp) +{ + return EOPNOTSUPP; +} + +static int +dpif_netlink_ct_get_timeout_policy(struct dpif *dpif OVS_UNUSED, + uint32_t tp_id, + struct ct_dpif_timeout_policy *tp) +{ + return EOPNOTSUPP; +} + +static int +dpif_netlink_ct_del_timeout_policy(struct dpif *dpif OVS_UNUSED, + uint32_t tp_id) +{ + return EOPNOTSUPP; +} + +static int +dpif_netlink_ct_timeout_policy_dump_start(struct dpif *dpif OVS_UNUSED, + void **statep) +{ + return EOPNOTSUPP; +} + +static int +dpif_netlink_ct_timeout_policy_dump_next(struct dpif *dpif OVS_UNUSED, + void *state, + struct ct_dpif_timeout_policy **tp) +{ + return EOPNOTSUPP; +} + +static int +dpif_netlink_ct_timeout_policy_dump_done(struct dpif *dpif OVS_UNUSED, + void *state) +{ + return EOPNOTSUPP; +} +#else +static int +dpif_netlink_ct_set_timeout_policy(struct dpif *dpif OVS_UNUSED, + const struct ct_dpif_timeout_policy *tp) +{ + struct nl_ct_timeout_policy nl_tp; + struct ds nl_tp_name = DS_EMPTY_INITIALIZER; + int i, err = 0; + + for (i = 0; i < ARRAY_SIZE(tp_protos); ++i) { + dpif_netlink_format_tp_name(tp->id, tp_protos[i].l3num, + tp_protos[i].l4num, &nl_tp_name); + ovs_strlcpy(nl_tp.name, ds_cstr(&nl_tp_name), sizeof nl_tp.name); + nl_tp.l3num = tp_protos[i].l3num; + nl_tp.l4num = tp_protos[i].l4num; + dpif_netlink_get_nl_tp_attrs(tp, tp_protos[i].l4num, &nl_tp); + err = nl_ct_set_timeout_policy(&nl_tp); + if (err) { + VLOG_WARN_RL(&error_rl, "failed to add timeout policy %s (%s)", + nl_tp.name, ovs_strerror(err)); + goto out; + } + } + +out: + ds_destroy(&nl_tp_name); + return err; +} + +static int +dpif_netlink_ct_get_timeout_policy(struct dpif *dpif OVS_UNUSED, + uint32_t tp_id, + struct ct_dpif_timeout_policy *tp) +{ + struct nl_ct_timeout_policy nl_tp; + struct ds nl_tp_name = DS_EMPTY_INITIALIZER; + int i, err = 0; + + tp->id = tp_id; + tp->present = 0; + for (i = 0; i < ARRAY_SIZE(tp_protos); ++i) { + dpif_netlink_format_tp_name(tp_id, tp_protos[i].l3num, + tp_protos[i].l4num, &nl_tp_name); + err = nl_ct_get_timeout_policy(ds_cstr(&nl_tp_name), &nl_tp); + + if (err) { + VLOG_WARN_RL(&error_rl, "failed to get timeout policy %s (%s)", + nl_tp.name, ovs_strerror(err)); + goto out; + } + dpif_netlink_set_ct_dpif_tp_attrs(&nl_tp, tp); + } + +out: + ds_destroy(&nl_tp_name); + return err; +} + +/* Returns 0 if all the sub timeout policies are deleted or + * not exist in the kernel. */ +static int +dpif_netlink_ct_del_timeout_policy(struct dpif *dpif OVS_UNUSED, + uint32_t tp_id) +{ + struct ds nl_tp_name = DS_EMPTY_INITIALIZER; + int i, err = 0; + + for (i = 0; i < ARRAY_SIZE(tp_protos); ++i) { + dpif_netlink_format_tp_name(tp_id, tp_protos[i].l3num, + tp_protos[i].l4num, &nl_tp_name); + err = nl_ct_del_timeout_policy(ds_cstr(&nl_tp_name)); + if (err == ENOENT) { + err = 0; + } + if (err) { + VLOG_WARN_RL(&error_rl, "failed to delete timeout policy %s (%s)", + ds_cstr(&nl_tp_name), ovs_strerror(err)); + goto out; + } + } + +out: + ds_destroy(&nl_tp_name); + return err; +} + +struct dpif_netlink_ct_timeout_policy_dump_state { + struct nl_ct_timeout_policy_dump_state *nl_dump_state; + struct hmap tp_dump_map; +}; + +struct dpif_netlink_tp_dump_node { + struct hmap_node hmap_node; /* node in tp_dump_map. */ + struct ct_dpif_timeout_policy *tp; + uint32_t present; +}; + +static struct dpif_netlink_tp_dump_node * +get_dpif_netlink_tp_dump_node_by_tp_id(uint32_t tp_id, + struct hmap *tp_dump_map) +{ + struct dpif_netlink_tp_dump_node *tp_dump_node; + + HMAP_FOR_EACH_WITH_HASH (tp_dump_node, hmap_node, hash_int(tp_id, 0), + tp_dump_map) { + if (tp_dump_node->tp->id == tp_id) { + return tp_dump_node; + } + } + return NULL; +} + +static void +update_dpif_netlink_tp_dump_node( + const struct nl_ct_timeout_policy *nl_tp, + struct dpif_netlink_tp_dump_node *tp_dump_node) +{ + int i; + + dpif_netlink_set_ct_dpif_tp_attrs(nl_tp, tp_dump_node->tp); + for (i = 0; i < DPIF_NL_TP_MAX; ++i) { + if (nl_tp->l3num == tp_protos[i].l3num && + nl_tp->l4num == tp_protos[i].l4num) { + tp_dump_node->present |= 1 << i; + break; + } + } +} + +static int +dpif_netlink_ct_timeout_policy_dump_start(struct dpif *dpif OVS_UNUSED, + void **statep) +{ + struct dpif_netlink_ct_timeout_policy_dump_state *dump_state; + int err; + + *statep = dump_state = xzalloc(sizeof *dump_state); + err = nl_ct_timeout_policy_dump_start(&dump_state->nl_dump_state); + if (err) { + free(dump_state); + return err; + } + hmap_init(&dump_state->tp_dump_map); + return 0; +} + +static int +dpif_netlink_ct_timeout_policy_dump_next(struct dpif *dpif OVS_UNUSED, + void *state, + struct ct_dpif_timeout_policy *tp) +{ + struct dpif_netlink_ct_timeout_policy_dump_state *dump_state = state; + struct dpif_netlink_tp_dump_node *tp_dump_node; + struct nl_ct_timeout_policy nl_tp; + uint32_t tp_id; + int err; + + do { + err = nl_ct_timeout_policy_dump_next(dump_state->nl_dump_state, + &nl_tp); + if (err) { + break; + } + + if (!ovs_scan(nl_tp.name, NL_TP_NAME_PREFIX"%"PRIu32, &tp_id)) { + continue; + } + + tp_dump_node = get_dpif_netlink_tp_dump_node_by_tp_id( + tp_id, &dump_state->tp_dump_map); + if (!tp_dump_node) { + tp_dump_node = xzalloc(sizeof *tp_dump_node); + tp_dump_node->tp = xzalloc(sizeof *tp_dump_node->tp); + tp_dump_node->tp->id = tp_id; + hmap_insert(&dump_state->tp_dump_map, &tp_dump_node->hmap_node, + hash_int(tp_id, 0)); + } + + update_dpif_netlink_tp_dump_node(&nl_tp, tp_dump_node); + if (tp_dump_node->present == DPIF_NL_ALL_TP) { + hmap_remove(&dump_state->tp_dump_map, &tp_dump_node->hmap_node); + *tp = *tp_dump_node->tp; + free(tp_dump_node->tp); + free(tp_dump_node); + break; + } + } while (true); + + /* Dump the incomplete timeout policy. */ + if (err == EOF) { + if (!hmap_is_empty(&dump_state->tp_dump_map)) { + struct hmap_node *hmap_node = hmap_first(&dump_state->tp_dump_map); + + hmap_remove(&dump_state->tp_dump_map, hmap_node); + tp_dump_node = CONTAINER_OF(hmap_node, + struct dpif_netlink_tp_dump_node, hmap_node); + *tp = *tp_dump_node->tp; + free(tp_dump_node->tp); + free(tp_dump_node); + return 0; + } + } + + return err; +} + +static int +dpif_netlink_ct_timeout_policy_dump_done(struct dpif *dpif OVS_UNUSED, + void *state) +{ + struct dpif_netlink_ct_timeout_policy_dump_state *dump_state = state; + int err; + + err = nl_ct_timeout_policy_dump_done(dump_state->nl_dump_state); + hmap_destroy(&dump_state->tp_dump_map); + free(dump_state); + return err; +} +#endif + /* Meters */ @@ -3429,6 +3885,12 @@ const struct dpif_class dpif_netlink_class = { dpif_netlink_ct_set_limits, dpif_netlink_ct_get_limits, dpif_netlink_ct_del_limits, + dpif_netlink_ct_set_timeout_policy, + dpif_netlink_ct_get_timeout_policy, + dpif_netlink_ct_del_timeout_policy, + dpif_netlink_ct_timeout_policy_dump_start, + dpif_netlink_ct_timeout_policy_dump_next, + dpif_netlink_ct_timeout_policy_dump_done, NULL, /* ipf_set_enabled */ NULL, /* ipf_set_min_frag */ NULL, /* ipf_set_max_nfrags */ diff --git a/lib/dpif-netlink.h b/lib/dpif-netlink.h index 0a9628088275..1e753994d747 100644 --- a/lib/dpif-netlink.h +++ b/lib/dpif-netlink.h @@ -23,6 +23,7 @@ #include "odp-netlink.h" #include "flow.h" +#include "netlink-conntrack.h" struct ofpbuf; diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index 12898b9e3c6d..79a2314500cf 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -80,6 +80,7 @@ dpif_flow_dump_thread_init(struct dpif_flow_dump_thread *thread, struct ct_dpif_dump_state; struct ct_dpif_entry; struct ct_dpif_tuple; +struct ct_dpif_timeout_policy; /* 'dpif_ipf_proto_status' and 'dpif_ipf_status' are presently in * sync with 'ipf_proto_status' and 'ipf_status', but more @@ -498,6 +499,43 @@ struct dpif_class { * list of 'struct ct_dpif_zone_limit' entries. */ int (*ct_del_limits)(struct dpif *, const struct ovs_list *zone_limits); + /* Connection tracking timeout policy */ + + /* A connection tracking timeout policy contains a list of timeout + * attributes that specifies timeout values on various connection states. + * In a datapath, the timeout policy is identified by a 4 bytes unsigned + * integer, and the unsupported timeout attributes are ignored. + * When a connection is committed it can be associated with a timeout + * policy, or it defaults to the datapath's default timeout policy. */ + + /* Sets timeout policy '*tp' into the datapath. */ + int (*ct_set_timeout_policy)(struct dpif *, + const struct ct_dpif_timeout_policy *tp); + /* Gets a timeout policy specified by tp_id and stores it into '*tp'.*/ + int (*ct_get_timeout_policy)(struct dpif *, uint32_t tp_id, + struct ct_dpif_timeout_policy *tp); + /* Deletes a timeout policy identified by 'tp_id'. */ + int (*ct_del_timeout_policy)(struct dpif *, uint32_t tp_id); + + /* Conntrack timeout policy dumping interface. + * + * These functions provide a datapath-agnostic dumping interface + * to the conntrack timeout policy provided by the datapaths. + * + * ct_timeout_policy_dump_start() should put in '*statep' a pointer to + * a newly allocated structure that will be passed by the caller to + * ct_timeout_policy_dump_next() and ct_timeout_policy_dump_done(). + * + * ct_timeout_policy_dump_next() fills a timeout policy into '*tp', + * and prepares to dump the next one on a subsequent invocation. + * + * ct_timeout_policy_dump_done() should perform any cleanup necessary + * (including deallocating the 'state' structure, if applicable). */ + int (*ct_timeout_policy_dump_start)(struct dpif *, void **statep); + int (*ct_timeout_policy_dump_next)(struct dpif *, void *state, + struct ct_dpif_timeout_policy *tp); + int (*ct_timeout_policy_dump_done)(struct dpif *, void *state); + /* IP Fragmentation. */ /* Disables or enables conntrack fragment reassembly. The default diff --git a/lib/netlink-conntrack.c b/lib/netlink-conntrack.c index 7631ba5d5d31..9bc0ddb66248 100644 --- a/lib/netlink-conntrack.c +++ b/lib/netlink-conntrack.c @@ -840,6 +840,369 @@ nl_ct_parse_helper(struct nlattr *nla, struct ct_dpif_helper *helper) return parsed; } +static int nl_ct_timeout_policy_max_attr[] = { + [IPPROTO_TCP] = CTA_TIMEOUT_TCP_MAX, + [IPPROTO_UDP] = CTA_TIMEOUT_UDP_MAX, + [IPPROTO_ICMP] = CTA_TIMEOUT_ICMP_MAX, + [IPPROTO_ICMPV6] = CTA_TIMEOUT_ICMPV6_MAX +}; + +static void +nl_ct_set_timeout_policy_attr(struct nl_ct_timeout_policy *nl_tp, + uint32_t attr, uint32_t val) +{ + nl_tp->present |= 1 << attr; + nl_tp->attrs[attr] = val; +} + +static int +nl_ct_parse_tcp_timeout_policy_data(struct nlattr *nla, + struct nl_ct_timeout_policy *nl_tp) +{ + static const struct nl_policy policy[] = { + [CTA_TIMEOUT_TCP_SYN_SENT] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_SYN_RECV] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_ESTABLISHED] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_FIN_WAIT] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_CLOSE_WAIT] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_LAST_ACK] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_TIME_WAIT] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_CLOSE] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_SYN_SENT2] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_RETRANS] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_TCP_UNACK] = { .type = NL_A_BE32, + .optional = false }, + }; + struct nlattr *attrs[ARRAY_SIZE(policy)]; + int i; + + if (!nl_parse_nested(nla, policy, attrs, ARRAY_SIZE(policy))) { + VLOG_ERR_RL(&rl, "Could not parse nested tcp timeout options. " + "Possibly incompatible Linux kernel version."); + return EINVAL; + } + + for (i = CTA_TIMEOUT_TCP_SYN_SENT; i <= CTA_TIMEOUT_TCP_UNACK; i++) { + nl_ct_set_timeout_policy_attr(nl_tp, i, + ntohl(nl_attr_get_be32(attrs[i]))); + } + return 0; +} + +static int +nl_ct_parse_udp_timeout_policy_data(struct nlattr *nla, + struct nl_ct_timeout_policy *nl_tp) +{ + static const struct nl_policy policy[] = { + [CTA_TIMEOUT_UDP_UNREPLIED] = { .type = NL_A_BE32, + .optional = false }, + [CTA_TIMEOUT_UDP_REPLIED] = { .type = NL_A_BE32, + .optional = false }, + }; + struct nlattr *attrs[ARRAY_SIZE(policy)]; + int i; + + if (!nl_parse_nested(nla, policy, attrs, ARRAY_SIZE(policy))) { + VLOG_ERR_RL(&rl, "Could not parse nested tcp timeout options. " + "Possibly incompatible Linux kernel version."); + return EINVAL; + } + + for (i = CTA_TIMEOUT_UDP_UNREPLIED; i <= CTA_TIMEOUT_UDP_REPLIED; i++) { + nl_ct_set_timeout_policy_attr(nl_tp, i, + ntohl(nl_attr_get_be32(attrs[i]))); + } + return 0; +} + +static int +nl_ct_parse_icmp_timeout_policy_data(struct nlattr *nla, + struct nl_ct_timeout_policy *nl_tp) +{ + static const struct nl_policy policy[] = { + [CTA_TIMEOUT_ICMP_TIMEOUT] = { .type = NL_A_BE32, + .optional = false }, + }; + struct nlattr *attrs[ARRAY_SIZE(policy)]; + + if (!nl_parse_nested(nla, policy, attrs, ARRAY_SIZE(policy))) { + VLOG_ERR_RL(&rl, "Could not parse nested icmp timeout options. " + "Possibly incompatible Linux kernel version."); + return EINVAL; + } + + nl_ct_set_timeout_policy_attr( + nl_tp, CTA_TIMEOUT_ICMP_TIMEOUT, + ntohl(nl_attr_get_be32(attrs[CTA_TIMEOUT_ICMP_TIMEOUT]))); + return 0; +} + +static int +nl_ct_parse_icmpv6_timeout_policy_data(struct nlattr *nla, + struct nl_ct_timeout_policy *nl_tp) +{ + static const struct nl_policy policy[] = { + [CTA_TIMEOUT_ICMPV6_TIMEOUT] = { .type = NL_A_BE32, + .optional = false }, + }; + struct nlattr *attrs[ARRAY_SIZE(policy)]; + + if (!nl_parse_nested(nla, policy, attrs, ARRAY_SIZE(policy))) { + VLOG_ERR_RL(&rl, "Could not parse nested icmpv6 timeout options. " + "Possibly incompatible Linux kernel version."); + return EINVAL; + } + + nl_ct_set_timeout_policy_attr( + nl_tp, CTA_TIMEOUT_ICMPV6_TIMEOUT, + ntohl(nl_attr_get_be32(attrs[CTA_TIMEOUT_ICMPV6_TIMEOUT]))); + return 0; +} + +static int +nl_ct_parse_timeout_policy_data(struct nlattr *nla, + struct nl_ct_timeout_policy *nl_tp) +{ + switch (nl_tp->l4num) { + case IPPROTO_TCP: + return nl_ct_parse_tcp_timeout_policy_data(nla, nl_tp); + case IPPROTO_UDP: + return nl_ct_parse_udp_timeout_policy_data(nla, nl_tp); + case IPPROTO_ICMP: + return nl_ct_parse_icmp_timeout_policy_data(nla, nl_tp); + case IPPROTO_ICMPV6: + return nl_ct_parse_icmpv6_timeout_policy_data(nla, nl_tp); + default: + return EINVAL; + } +} + +static int +nl_ct_timeout_policy_from_ofpbuf(struct ofpbuf *buf, + struct nl_ct_timeout_policy *nl_tp, + bool default_tp) +{ + static const struct nl_policy policy[] = { + [CTA_TIMEOUT_NAME] = { .type = NL_A_STRING, .optional = false }, + [CTA_TIMEOUT_L3PROTO] = { .type = NL_A_BE16, .optional = false }, + [CTA_TIMEOUT_L4PROTO] = { .type = NL_A_U8, .optional = false }, + [CTA_TIMEOUT_DATA] = { .type = NL_A_NESTED, .optional = false } + }; + static const struct nl_policy policy_default_tp[] = { + [CTA_TIMEOUT_L3PROTO] = { .type = NL_A_BE16, .optional = false }, + [CTA_TIMEOUT_L4PROTO] = { .type = NL_A_U8, .optional = false }, + [CTA_TIMEOUT_DATA] = { .type = NL_A_NESTED, .optional = false } + }; + + struct nlattr *attrs[ARRAY_SIZE(policy)]; + struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size); + struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg); + struct nfgenmsg *nfmsg = ofpbuf_try_pull(&b, sizeof *nfmsg); + int err; + + if (!nlmsg || !nfmsg + || NFNL_SUBSYS_ID(nlmsg->nlmsg_type) != NFNL_SUBSYS_CTNETLINK_TIMEOUT + || nfmsg->version != NFNETLINK_V0 + || !nl_policy_parse(&b, 0, default_tp ? policy_default_tp : policy, + attrs, default_tp ? ARRAY_SIZE(policy_default_tp) : + ARRAY_SIZE(policy))) { + return EINVAL; + } + + if (!default_tp) { + ovs_strlcpy(nl_tp->name, nl_attr_get_string(attrs[CTA_TIMEOUT_NAME]), + sizeof nl_tp->name); + } + nl_tp->l3num = ntohs(nl_attr_get_be16(attrs[CTA_TIMEOUT_L3PROTO])); + nl_tp->l4num = nl_attr_get_u8(attrs[CTA_TIMEOUT_L4PROTO]); + nl_tp->present = 0; + + err = nl_ct_parse_timeout_policy_data(attrs[CTA_TIMEOUT_DATA], nl_tp); + return err; +} + +int +nl_ct_set_timeout_policy(const struct nl_ct_timeout_policy *nl_tp) +{ + struct ofpbuf buf; + size_t offset; + int i, err; + + ofpbuf_init(&buf, 512); + nl_msg_put_nfgenmsg(&buf, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK_TIMEOUT, + IPCTNL_MSG_TIMEOUT_NEW, NLM_F_REQUEST | NLM_F_CREATE + | NLM_F_ACK | NLM_F_REPLACE); + + nl_msg_put_string(&buf, CTA_TIMEOUT_NAME, nl_tp->name); + nl_msg_put_be16(&buf, CTA_TIMEOUT_L3PROTO, htons(nl_tp->l3num)); + nl_msg_put_u8(&buf, CTA_TIMEOUT_L4PROTO, nl_tp->l4num); + + offset = nl_msg_start_nested(&buf, CTA_TIMEOUT_DATA); + for (i = 1; i <= nl_ct_timeout_policy_max_attr[nl_tp->l4num]; ++i) { + if (nl_tp->present & 1 << i) { + nl_msg_put_be32(&buf, i, htonl(nl_tp->attrs[i])); + } + } + nl_msg_end_nested(&buf, offset); + + err = nl_transact(NETLINK_NETFILTER, &buf, NULL); + ofpbuf_uninit(&buf); + return err; +} + +int +nl_ct_set_default_timeout_policy(const struct nl_ct_timeout_policy *nl_tp) +{ + struct ofpbuf buf; + size_t offset; + int i, err; + + ofpbuf_init(&buf, 512); + nl_msg_put_nfgenmsg(&buf, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK_TIMEOUT, + IPCTNL_MSG_TIMEOUT_DEFAULT_SET, NLM_F_REQUEST + | NLM_F_ACK | NLM_F_REPLACE); + + nl_msg_put_be16(&buf, CTA_TIMEOUT_L3PROTO, htons(nl_tp->l3num)); + nl_msg_put_u8(&buf, CTA_TIMEOUT_L4PROTO, nl_tp->l4num); + + offset = nl_msg_start_nested(&buf, CTA_TIMEOUT_DATA); + for (i = 1; i <= nl_ct_timeout_policy_max_attr[nl_tp->l4num]; ++i) { + if (nl_tp->present & 1 << i) { + nl_msg_put_be32(&buf, i, htonl(nl_tp->attrs[i])); + } + } + nl_msg_end_nested(&buf, offset); + + err = nl_transact(NETLINK_NETFILTER, &buf, NULL); + ofpbuf_uninit(&buf); + return err; +} + +int +nl_ct_get_timeout_policy(const char *tp_name, + struct nl_ct_timeout_policy *nl_tp) +{ + struct ofpbuf request, *reply; + int err; + + ofpbuf_init(&request, 512); + nl_msg_put_nfgenmsg(&request, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK_TIMEOUT, + IPCTNL_MSG_TIMEOUT_GET, NLM_F_REQUEST | NLM_F_ACK); + nl_msg_put_string(&request, CTA_TIMEOUT_NAME, tp_name); + err = nl_transact(NETLINK_NETFILTER, &request, &reply); + if (err) { + goto out; + } + + err = nl_ct_timeout_policy_from_ofpbuf(reply, nl_tp, false); + +out: + ofpbuf_uninit(&request); + ofpbuf_delete(reply); + return err; +} + +int +nl_ct_get_default_timeout_policy(uint16_t l3num, uint8_t l4num, + struct nl_ct_timeout_policy *nl_tp) +{ + struct ofpbuf request, *reply; + int err; + + ofpbuf_init(&request, 512); + nl_msg_put_nfgenmsg(&request, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK_TIMEOUT, + IPCTNL_MSG_TIMEOUT_DEFAULT_GET, + NLM_F_REQUEST | NLM_F_ACK); + + nl_msg_put_be16(&request, CTA_TIMEOUT_L3PROTO, htons(l3num)); + nl_msg_put_u8(&request, CTA_TIMEOUT_L4PROTO, l4num); + err = nl_transact(NETLINK_NETFILTER, &request, &reply); + if (err) { + goto out; + } + + err = nl_ct_timeout_policy_from_ofpbuf(reply, nl_tp, true); + +out: + ofpbuf_uninit(&request); + ofpbuf_delete(reply); + return err; +} + +int +nl_ct_del_timeout_policy(const char *tp_name) +{ + struct ofpbuf buf; + int err; + + ofpbuf_init(&buf, 64); + nl_msg_put_nfgenmsg(&buf, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK_TIMEOUT, + IPCTNL_MSG_TIMEOUT_DELETE, NLM_F_REQUEST | NLM_F_ACK); + + nl_msg_put_string(&buf, CTA_TIMEOUT_NAME, tp_name); + err = nl_transact(NETLINK_NETFILTER, &buf, NULL); + ofpbuf_uninit(&buf); + return err; +} + +struct nl_ct_timeout_policy_dump_state { + struct nl_dump dump; + struct ofpbuf buf; +}; + +int +nl_ct_timeout_policy_dump_start( + struct nl_ct_timeout_policy_dump_state **statep) +{ + struct ofpbuf request; + struct nl_ct_timeout_policy_dump_state *state; + + *statep = state = xzalloc(sizeof *state); + ofpbuf_init(&request, 512); + nl_msg_put_nfgenmsg(&request, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK_TIMEOUT, + IPCTNL_MSG_TIMEOUT_GET, + NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); + + nl_dump_start(&state->dump, NETLINK_NETFILTER, &request); + ofpbuf_uninit(&request); + ofpbuf_init(&state->buf, NL_DUMP_BUFSIZE); + return 0; +} + +int +nl_ct_timeout_policy_dump_next(struct nl_ct_timeout_policy_dump_state *state, + struct nl_ct_timeout_policy *nl_tp) +{ + struct ofpbuf reply; + int err; + + if (!nl_dump_next(&state->dump, &reply, &state->buf)) { + return EOF; + } + err = nl_ct_timeout_policy_from_ofpbuf(&reply, nl_tp, false); + ofpbuf_uninit(&reply); + return err; +} + +int +nl_ct_timeout_policy_dump_done(struct nl_ct_timeout_policy_dump_state *state) +{ + int err = nl_dump_done(&state->dump); + ofpbuf_uninit(&state->buf); + free(state); + return err; +} + /* Translate netlink entry status flags to CT_DPIF_TCP status flags. */ static uint32_t ips_status_to_dpif_flags(uint32_t status) diff --git a/lib/netlink-conntrack.h b/lib/netlink-conntrack.h index 8b536fd65ba8..ae6e428e0929 100644 --- a/lib/netlink-conntrack.h +++ b/lib/netlink-conntrack.h @@ -17,9 +17,12 @@ #ifndef NETLINK_CONNTRACK_H #define NETLINK_CONNTRACK_H +#include + #include "byte-order.h" #include "compiler.h" #include "ct-dpif.h" +#include "netlink-socket.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/hmap.h" #include "openvswitch/ofpbuf.h" @@ -33,7 +36,18 @@ enum nl_ct_event_type { NL_CT_EVENT_DELETE = 1 << 2, }; +#define NL_CT_TIMEOUT_POLICY_MAX_ATTR (CTA_TIMEOUT_TCP_MAX + 1) + +struct nl_ct_timeout_policy { + char name[CTNL_TIMEOUT_NAME_MAX]; + uint16_t l3num; + uint8_t l4num; + uint32_t attrs[NL_CT_TIMEOUT_POLICY_MAX_ATTR]; + uint32_t present; +}; + struct nl_ct_dump_state; +struct nl_ct_timeout_policy_dump_state; int nl_ct_dump_start(struct nl_ct_dump_state **, const uint16_t *zone, int *ptot_bkts); @@ -44,6 +58,21 @@ int nl_ct_flush(void); int nl_ct_flush_zone(uint16_t zone); int nl_ct_flush_tuple(const struct ct_dpif_tuple *, uint16_t zone); +int nl_ct_set_timeout_policy(const struct nl_ct_timeout_policy *nl_tp); +int nl_ct_set_default_timeout_policy(const struct nl_ct_timeout_policy *nl_tp); +int nl_ct_get_timeout_policy(const char *tp_name, + struct nl_ct_timeout_policy *nl_tp); +int nl_ct_get_default_timeout_policy(uint16_t l3num, uint8_t l4num, + struct nl_ct_timeout_policy *nl_tp); +int nl_ct_del_timeout_policy(const char *tp_name); +int nl_ct_timeout_policy_dump_start( + struct nl_ct_timeout_policy_dump_state **statep); +int nl_ct_timeout_policy_dump_next( + struct nl_ct_timeout_policy_dump_state *state, + struct nl_ct_timeout_policy *nl_tp); +int nl_ct_timeout_policy_dump_done( + struct nl_ct_timeout_policy_dump_state *state); + bool nl_ct_parse_entry(struct ofpbuf *, struct ct_dpif_entry *, enum nl_ct_event_type *); void nl_ct_format_event_entry(const struct ct_dpif_entry *, diff --git a/lib/netlink-protocol.h b/lib/netlink-protocol.h index c0617dfad21f..bf631b1a14d0 100644 --- a/lib/netlink-protocol.h +++ b/lib/netlink-protocol.h @@ -48,6 +48,7 @@ #define NLM_F_ECHO 0x008 #define NLM_F_ROOT 0x100 +#define NLM_F_REPLACE 0x100 #define NLM_F_MATCH 0x200 #define NLM_F_EXCL 0x200 #define NLM_F_ATOMIC 0x400 From patchwork Thu Aug 1 22:07:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 1140791 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="cgTqPOGz"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4604Gv32Q0z9s3Z for ; Fri, 2 Aug 2019 08:10:14 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 695501684; Thu, 1 Aug 2019 22:07:53 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 3BDDB1661 for ; Thu, 1 Aug 2019 22:07:52 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id BB332832 for ; Thu, 1 Aug 2019 22:07:50 +0000 (UTC) Received: by mail-wm1-f52.google.com with SMTP id u25so54152591wmc.4 for ; Thu, 01 Aug 2019 15:07:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=B8BazAJNPQNxlOp5ahiktIHSikqkv4VWI7S9HzNyQ7A=; b=cgTqPOGzsWS7+bxj4N15CJuP/QH2smzKOIEkQWrBMmSnrAs4PfXvId6UfLRlhvbdtk tgbRnu7pZPINJVrJ4ZqwZxfP1+idi4tDCcepRl+iGvOOSg3rzY3Qj7zBkHbeE6uVxw6a 1q6mOVlcN2SH3PXnrxuM97vYkjD7OHci2g6+QStr+NGHNysIPY4n+eowhWAuJAtCv8hE eWNZIa13BZe8CsGBJub0yn7/8+GYZlF6TUCUt4CNNVBO1MJVbkTbWJgL5BDUUS2Mj++7 ja/6Gb6iHv6TEwDD6/DMlmO617rRAjiTicOxbsYuPAN6jhgmLyZCJO2Oul/057yxd6ii CtIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=B8BazAJNPQNxlOp5ahiktIHSikqkv4VWI7S9HzNyQ7A=; b=DWCHahnunPttVyUHMsSF0kK+tUT/o+uXVRhhOQS20Q8ul/lEBvNm7nIcbA11MCTf1U e+qZ+3vgLh8SkmcRQl9Oonu0pTJVS2BfBCOSMaMbRoAnMvpAlEnQpyUXi/X16l85IDLK QCeGV0817cG5+RfEY+ksUlbUR5dhOAFSQ57x2wklI4BdqNabieBQvSLG+VXu6b/Sf3+h Q1ZPSy9XboD+4a0XklRcG1Z+9+i5Ozz4lvANVl6FhIfHqMApHkwxxbt4SztzDAdpESeG qerJdb1YOfXKbRPWa3uU+vAyFRxcL+k961+bbbHVYpUON2mWoJa8xMJOYmVbr5iZy7H0 qjSw== X-Gm-Message-State: APjAAAXhEpqVytW+ET/LG3qyougar1lfK9aCdT1yEP2cdnwjkGhtQryV iaCoZNoVY+6RfwfR3FHVQhWOpnyD X-Google-Smtp-Source: APXvYqwnDaysEFf9o8yofUzqNI4CsxrrAM7Roq4v+FlLWEC8cDOqeiiYUJ9fzwP5OM5VcPXJsXQ9Xw== X-Received: by 2002:a1c:3b02:: with SMTP id i2mr521104wma.23.1564697268891; Thu, 01 Aug 2019 15:07:48 -0700 (PDT) Received: from vm-main.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id z19sm54128982wmi.7.2019.08.01.15.07.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Aug 2019 15:07:48 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Thu, 1 Aug 2019 15:07:29 -0700 Message-Id: <1564697253-37992-6-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> References: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 5/9] ofproto-dpif: Consume CT_Zone, and CT_Timeout_Policy tables X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch consumes the CT_Zone and CT_Timeout_Policy tables, maintains the zone-based timeout policy in the vswitchd. Whenever there is a database change, vswitchd will read the datapath, CT_Zone, and CT_Timeout_Policy tables from ovsdb to detect if the is any timeout policy changes. If a new timeout policy is added, it stores the information in per datapath type internal datapath structure in struct dpif-backer, and pushes down the conntrack timeout policy into the datapath via dpif interface. If a timeout policy is no longer used, vswitchd may not be able to remove it from datapath immediately since the datapath flow may still reference that. Instead, we keep an timeout policy kill list, that vswitchd will goes back to the list regularly and try to kill the unused timeout policies. Signed-off-by: Yi-Hung Wei --- ofproto/ofproto-dpif.c | 266 +++++++++++++++++++++++++++++++++++++++++++++ ofproto/ofproto-dpif.h | 10 ++ ofproto/ofproto-provider.h | 8 ++ ofproto/ofproto.c | 20 ++++ ofproto/ofproto.h | 4 + vswitchd/bridge.c | 41 +++++++ 6 files changed, 349 insertions(+) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 751535249e21..6336494e0bc8 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -156,6 +156,25 @@ struct ofport_dpif { size_t n_qdscp; }; +struct ct_timeout_policy { + struct uuid uuid; + unsigned int last_used_seqno; + struct ct_dpif_timeout_policy cdtp; + struct cmap_node node; /* Element in struct dpif_backer's + * "ct_tps" cmap. */ + struct ovs_list list_node; /* Element in struct dpif_backer's + * "ct_tp_kill_list" list. */ +}; + +struct ct_zone { + uint16_t id; + unsigned int last_used_seqno; + struct uuid tp_uuid; /* uuid that identifies a timeout policy in + * struct dpif_backer's "ct_tps" cmap. */ + struct cmap_node node; /* Element in struct dpif_backer's + * "ct_zones" cmap. */ +}; + static odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *, ofp_port_t); @@ -196,6 +215,8 @@ static struct hmap all_ofproto_dpifs_by_uuid = static bool ofproto_use_tnl_push_pop = true; static void ofproto_unixctl_init(void); +static void destroy_ct_zone_timeout_policy(struct dpif_backer *backer); +static void init_ct_zone_timeout_policy(struct dpif_backer *backer); static inline struct ofproto_dpif * ofproto_dpif_cast(const struct ofproto *ofproto) @@ -683,6 +704,7 @@ close_dpif_backer(struct dpif_backer *backer, bool del) } dpif_close(backer->dpif); id_pool_destroy(backer->meter_ids); + destroy_ct_zone_timeout_policy(backer); free(backer); } @@ -694,6 +716,8 @@ struct odp_garbage { static void check_support(struct dpif_backer *backer); +#define MAX_TIMEOUT_POLICY_ID UINT32_MAX + static int open_dpif_backer(const char *type, struct dpif_backer **backerp) { @@ -811,6 +835,8 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp) backer->meter_ids = NULL; } + init_ct_zone_timeout_policy(backer); + /* Make a pristine snapshot of 'support' into 'boottime_support'. * 'boottime_support' can be checked to prevent 'support' to be changed * beyond the datapath capabilities. In case 'support' is changed by @@ -5086,6 +5112,244 @@ ct_flush(const struct ofproto *ofproto_, const uint16_t *zone) ct_dpif_flush(ofproto->backer->dpif, zone, NULL); } +static struct ct_zone * +ct_zone_lookup(struct cmap *ct_zones, uint16_t zone_id) +{ + struct ct_zone *zone; + + CMAP_FOR_EACH_WITH_HASH (zone, node, hash_int(zone_id, 0), ct_zones) { + if (zone->id == zone_id) { + return zone; + } + } + return NULL; +} + +static struct ct_zone * +ct_zone_alloc(uint16_t zone_id) +{ + struct ct_zone *zone; + + zone = xzalloc(sizeof *zone); + zone->id = zone_id; + + return zone; +} + +static void +ct_zone_remove_and_destroy(struct dpif_backer *backer, struct ct_zone *zone) +{ + cmap_remove(&backer->ct_zones, &zone->node, hash_int(zone->id, 0)); + ovsrcu_postpone(free, zone); +} + +static struct ct_timeout_policy * +ct_timeout_policy_lookup(struct cmap *ct_tps, struct uuid *uuid) +{ + struct ct_timeout_policy *tp; + + CMAP_FOR_EACH_WITH_HASH (tp, node, uuid_hash(uuid), ct_tps) { + if (uuid_equals(&tp->uuid, uuid)) { + return tp; + } + } + return NULL; +} + +static struct ct_timeout_policy * +ct_timeout_policy_alloc(struct ovsrec_ct_timeout_policy *tp_cfg, + struct id_pool *tp_ids) +{ + struct ct_timeout_policy *tp; + size_t i; + + tp = xzalloc(sizeof *tp); + tp->uuid = tp_cfg->header_.uuid; + for (i = 0; i < tp_cfg->n_timeouts; i++) { + ct_dpif_set_timeout_policy_attr_by_name(&tp->cdtp, + tp_cfg->key_timeouts[i], tp_cfg->value_timeouts[i]); + } + if (!id_pool_alloc_id(tp_ids, &tp->cdtp.id)) { + VLOG_WARN_RL(&rl, "failed to allocate timeout policy id."); + free(tp); + return NULL; + } + + return tp; +} + +static void +ct_timeout_policy_destroy(struct dpif_backer *backer, + struct ct_timeout_policy *tp) +{ + id_pool_free_id(backer->timeout_policy_ids, tp->cdtp.id); + ovsrcu_postpone(free, tp); +} + +static bool +ct_timeout_policy_update(struct ovsrec_ct_timeout_policy *tp_cfg, + struct ct_timeout_policy *tp) +{ + size_t i; + bool changed = false; + + for (i = 0; i < tp_cfg->n_timeouts; i++) { + changed |= ct_dpif_set_timeout_policy_attr_by_name(&tp->cdtp, + tp_cfg->key_timeouts[i], tp_cfg->value_timeouts[i]); + } + return changed; +} + +static void +init_ct_zone_timeout_policy(struct dpif_backer *backer) +{ + cmap_init(&backer->ct_zones); + cmap_init(&backer->ct_tps); + backer->timeout_policy_ids = id_pool_create(0, MAX_TIMEOUT_POLICY_ID); + ovs_list_init(&backer->ct_tp_kill_list); + + /* Remove existing timeout policy from datapath. */ + struct ct_dpif_timeout_policy cdtp; + struct ct_timeout_policy *tp; + void *state; + int err; + + err = ct_dpif_timeout_policy_dump_start(backer->dpif, &state); + if (err) { + return; + } + + while (!(err = ct_dpif_timeout_policy_dump_next(backer->dpif, state, + &cdtp))) { + tp = xzalloc(sizeof *tp); + tp->cdtp = cdtp; + id_pool_add(backer->timeout_policy_ids, cdtp.id); + ovs_list_insert(&backer->ct_tp_kill_list, &tp->list_node); + } + + ct_dpif_timeout_policy_dump_done(backer->dpif, state); +} + +static void +destroy_ct_zone_timeout_policy(struct dpif_backer *backer) +{ + struct ct_timeout_policy *tp; + struct ct_zone *zone; + + CMAP_FOR_EACH (zone, node, &backer->ct_zones) { + ct_zone_remove_and_destroy(backer, zone); + } + + CMAP_FOR_EACH (tp, node, &backer->ct_tps) { + cmap_remove(&backer->ct_tps, &tp->node, uuid_hash(&tp->uuid)); + ct_timeout_policy_destroy(backer, tp); + } + + cmap_destroy(&backer->ct_zones); + cmap_destroy(&backer->ct_tps); + id_pool_destroy(backer->timeout_policy_ids); +} + +static void +ct_zone_timeout_policy_revalidate(struct dpif_backer *backer, + unsigned int idl_seqno) +{ + struct ct_timeout_policy *tp; + struct ct_zone *zone; + + CMAP_FOR_EACH (zone, node, &backer->ct_zones) { + if (zone->last_used_seqno != idl_seqno) { + ct_zone_remove_and_destroy(backer, zone); + } + } + + CMAP_FOR_EACH (tp, node, &backer->ct_tps) { + if (tp->last_used_seqno != idl_seqno) { + /* Even timeout policy is not referenced by any ct_zone in the + * database, vswitchd may not be able to delete it right away + * since the datapath flow may still reference to the timeout + * policy. Move the timeout policy to ct_tp_kill_list and try to + * delete it when possible. */ + cmap_remove(&backer->ct_tps, &tp->node, uuid_hash(&tp->uuid)); + ovs_list_push_back(&backer->ct_tp_kill_list, &tp->list_node); + } + } +} + +static void +ct_zone_timeout_policy_sweep(const struct ofproto *ofproto) +{ + struct dpif_backer *backer = ofproto_dpif_cast(ofproto)->backer; + struct ct_timeout_policy *tp; + int err; + + if (!ovs_list_is_empty(&backer->ct_tp_kill_list)) { + LIST_FOR_EACH (tp, list_node, &backer->ct_tp_kill_list) { + err = ct_dpif_del_timeout_policy(backer->dpif, tp->cdtp.id); + if (!err) { + ovs_list_remove(&tp->list_node); + ct_timeout_policy_destroy(backer, tp); + } else { + VLOG_INFO_RL(&rl, "Failed to delete timeout policy id = " + "%"PRIu32" %s", tp->cdtp.id, ovs_strerror(err)); + } + } + } +} + +static void +ct_zone_timeout_policy_reconfig(const struct ofproto *ofproto, + const struct ovsrec_datapath *dp_cfg, + unsigned int idl_seqno) +{ + struct dpif_backer *backer = ofproto_dpif_cast(ofproto)->backer; + struct ovsrec_ct_timeout_policy *tp_cfg; + struct ovsrec_ct_zone *zone_cfg; + struct ct_timeout_policy *tp; + struct ct_zone *zone; + uint16_t zone_id; + bool new_zone; + size_t i; + + for (i = 0; i < dp_cfg->n_ct_zones; i++) { + /* Update ct_zone config. */ + zone_cfg = dp_cfg->value_ct_zones[i]; + zone_id = dp_cfg->key_ct_zones[i]; + zone = ct_zone_lookup(&backer->ct_zones, zone_id); + if (!zone) { + new_zone = true; + zone = ct_zone_alloc(zone_id); + } else { + new_zone = false; + } + zone->last_used_seqno = idl_seqno; + + /* Update timeout policy. */ + tp_cfg = zone_cfg->timeout_policy; + tp = ct_timeout_policy_lookup(&backer->ct_tps, &tp_cfg->header_.uuid); + if (!tp) { + tp = ct_timeout_policy_alloc(tp_cfg, backer->timeout_policy_ids); + if (tp) { + cmap_insert(&backer->ct_tps, &tp->node, uuid_hash(&tp->uuid)); + ct_dpif_set_timeout_policy(backer->dpif, &tp->cdtp); + } + } else { + if (ct_timeout_policy_update(tp_cfg, tp)) { + ct_dpif_set_timeout_policy(backer->dpif, &tp->cdtp); + } + } + tp->last_used_seqno = idl_seqno; + + /* Link zone with new timeout policy. */ + zone->tp_uuid = tp_cfg->header_.uuid; + if (new_zone) { + cmap_insert(&backer->ct_zones, &zone->node, hash_int(zone_id, 0)); + } + } + ct_zone_timeout_policy_revalidate(backer, idl_seqno); + ct_zone_timeout_policy_sweep(ofproto); +} + static bool set_frag_handling(struct ofproto *ofproto_, enum ofputil_frag_handling frag_handling) @@ -6189,4 +6453,6 @@ const struct ofproto_class ofproto_dpif_class = { get_datapath_version, /* get_datapath_version */ type_set_config, ct_flush, /* ct_flush */ + ct_zone_timeout_policy_reconfig, + ct_zone_timeout_policy_sweep, }; diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index cd5321eb942c..170edf0e0e70 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -245,6 +245,16 @@ struct dpif_backer { /* Meter. */ struct id_pool *meter_ids; /* Datapath meter allocation. */ + /* Connection tracking */ + struct id_pool *timeout_policy_ids; /* Datapath timeout policy id + * allocation. */ + struct cmap ct_zones; /* "struct ct_zone"s indexed by + * zone id. */ + struct cmap ct_tps; /* "struct ct_timeout_policy"s + * indexed by uuid. */ + struct ovs_list ct_tp_kill_list; /* a list of timeout policy to be + * deleted. */ + /* Version string of the datapath stored in OVSDB. */ char *dp_version_string; diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 7907d4bfb416..41e07f0ee23e 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -58,6 +58,7 @@ #include "tun-metadata.h" #include "versions.h" #include "vl-mff-map.h" +#include "vswitch-idl.h" struct match; struct ofputil_flow_mod; @@ -1872,6 +1873,13 @@ struct ofproto_class { /* Flushes the connection tracking tables. If 'zone' is not NULL, * only deletes connections in '*zone'. */ void (*ct_flush)(const struct ofproto *, const uint16_t *zone); + + /* Reconfigures the zone-based conntrack tiemout policy based on the + * ovsdb configuration. */ + void (*ct_zone_timeout_policy_reconfig)(const struct ofproto *ofproto_, + const struct ovsrec_datapath *dp_cfg, unsigned int idl_seqno); + /* Cleans up the to be deleted timeout policy in the pending kill list. */ + void (*ct_zone_timeout_policy_sweep)(const struct ofproto *ofproto_); }; extern const struct ofproto_class ofproto_dpif_class; diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 1d6fc00696f8..373b8a4eba0c 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -935,6 +935,26 @@ ofproto_get_flow_restore_wait(void) return flow_restore_wait; } +/* Connection tracking configuration. */ +void +ofproto_ct_zone_timeout_policy_reconfig(const struct ofproto *ofproto, + const struct ovsrec_datapath *dp_cfg, + unsigned int idl_seqno) +{ + if (ofproto->ofproto_class->ct_zone_timeout_policy_reconfig) { + ofproto->ofproto_class->ct_zone_timeout_policy_reconfig( + ofproto, dp_cfg, idl_seqno); + } +} + +void +ofproto_ct_zone_timeout_policy_sweep(const struct ofproto *ofproto) +{ + if (ofproto->ofproto_class->ct_zone_timeout_policy_sweep) { + ofproto->ofproto_class->ct_zone_timeout_policy_sweep(ofproto); + } +} + /* Spanning Tree Protocol (STP) configuration. */ diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 6e4afffa17e0..2ae42374be36 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -52,6 +52,7 @@ struct ovs_list; struct lldp_status; struct aa_settings; struct aa_mapping_settings; +struct ovsrec_datapath; /* Needed for the lock annotations. */ extern struct ovs_mutex ofproto_mutex; @@ -362,6 +363,9 @@ int ofproto_get_stp_status(struct ofproto *, struct ofproto_stp_status *); int ofproto_set_rstp(struct ofproto *, const struct ofproto_rstp_settings *); int ofproto_get_rstp_status(struct ofproto *, struct ofproto_rstp_status *); void ofproto_set_vlan_limit(int vlan_limit); +void ofproto_ct_zone_timeout_policy_reconfig(const struct ofproto *ofproto, + const struct ovsrec_datapath *dp_cfg, unsigned int idl_seqno); +void ofproto_ct_zone_timeout_policy_sweep(const struct ofproto *ofproto); /* Configuration of ports. */ void ofproto_port_unregister(struct ofproto *, ofp_port_t ofp_port); diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 2976771aeaba..39b7de7d8182 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -220,6 +220,11 @@ static long long int stats_timer = LLONG_MIN; #define AA_REFRESH_INTERVAL (1000) /* In milliseconds. */ static long long int aa_refresh_timer = LLONG_MIN; +/* Each time this timer expires, the bridge tries to delete the timeout + * policies in the kill list. */ +#define CT_ZONE_TIMEOUT_POLICY_TIMER_INTERVAL (5000) /* In milliseconds. */ +static long long int ct_zone_timeout_policy_timer = LLONG_MIN; + /* Whenever system interfaces are added, removed or change state, the bridge * will be reconfigured. */ @@ -588,6 +593,40 @@ config_ofproto_types(const struct smap *other_config) } static void +reconfigure_conntrack_timeout_policy(const struct ovsrec_open_vswitch *cfg) +{ + struct bridge *br; + int i; + + for (i = 0; i < cfg->n_datapaths; i++) { + const struct ovsrec_datapath *dp_cfg = cfg->value_datapaths[i]; + char *key = cfg->key_datapaths[i]; + + HMAP_FOR_EACH (br, node, &all_bridges) { + if (!strcmp(br->type, key)) { + ofproto_ct_zone_timeout_policy_reconfig(br->ofproto, dp_cfg, + idl_seqno); + } + break; + } + } +} + +static void +run_ct_zone_timeout_policy_sweep(void) +{ + struct bridge *br; + + if (time_msec() >= ct_zone_timeout_policy_timer) { + HMAP_FOR_EACH (br, node, &all_bridges) { + ofproto_ct_zone_timeout_policy_sweep(br->ofproto); + } + ct_zone_timeout_policy_timer = time_msec() + + CT_ZONE_TIMEOUT_POLICY_TIMER_INTERVAL; + } +} + +static void bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) { struct sockaddr_in *managers; @@ -669,6 +708,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) } reconfigure_system_stats(ovs_cfg); + reconfigure_conntrack_timeout_policy(ovs_cfg); /* Complete the configuration. */ sflow_bridge_number = 0; @@ -3082,6 +3122,7 @@ bridge_run(void) run_stats_update(); run_status_update(); run_system_stats(); + run_ct_zone_timeout_policy_sweep(); } void From patchwork Thu Aug 1 22:07:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 1140793 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hdgPPbpv"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4604J44wLJz9s3Z for ; Fri, 2 Aug 2019 08:11:16 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id E7BA916BD; Thu, 1 Aug 2019 22:07:54 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 409C01661 for ; Thu, 1 Aug 2019 22:07:53 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wm1-f65.google.com (mail-wm1-f65.google.com [209.85.128.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 57AD082B for ; Thu, 1 Aug 2019 22:07:52 +0000 (UTC) Received: by mail-wm1-f65.google.com with SMTP id l2so64471636wmg.0 for ; Thu, 01 Aug 2019 15:07:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=vYyOv9LeG+eMK8FutP1Db6ZUI1hUlwVWyBLcAhVfMis=; b=hdgPPbpv5ogqEFHNsY/dTxpPaPNuoavUSpqAA3nTSa2Rn664/PJl4i9GiwX/uQKOOG wbR+V9feNODxKDENnNYFWYFdTmplnyB1Ei46NS926rPF9UzhVPVBF23QTSzSTSjpQNcm RNxenNH+LN1W3zeFhdJ3KqvKw0z7IeXN6pH1rL/yM3AL6q1hUVmVTGEm7e6vbV/Rq8ie NlK74Ge88/e5F+03Y+M+X0wKCP6Un+v5jyx7n8aq4BAS1ywLsUrGA4gEbH7mR2g30KDU 4Rg5h9hR35Gs+MZW1eDhkUkHDZW64bU8Dgc4App6VKU0uQSDjTZ4r2NyWdrnhgWW5aWS 2vXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=vYyOv9LeG+eMK8FutP1Db6ZUI1hUlwVWyBLcAhVfMis=; b=EUlnpb1I/xlR00/SNAD0GdrwC1pzwjLrTqN1K3TscIOVuajolODwQCIiPw9eHZPriY +smg4dKdwEe452E1VQxsIYrFSvDoCDDtPmAcDnWd0d7+qvyH8HLU9U3ZQFNshWuiSQDP PUzBIkVTawPcoA1Dh2LlPS79jnZ1HdN+dQdL61BcUUrBZVK78UFpnUlpw5l6f/egWfVe sSG/LoigAEYIUo9EzTfuQljAeW/ZoLvu1G7QWwglM15+ThkqICiZpnt/Lfo1/R0bo1iV vN39UpjretFwdvMjGSDRw6eqM8ocCQ+5uQj1QWM+wEae8OVSroPuklZh27qBZOgG0tcL 5FfQ== X-Gm-Message-State: APjAAAUN6dqi3ajHD2uLOU4jZoH0ABLn5VOGdRkiVTAkGQcIBis3mYPd sShAucj8R/U5JilcMWkbcOLVhehw X-Google-Smtp-Source: APXvYqwyV4Sgq6RxKlkiPUyhP6AgoJFCgjwu9zME6rLhOTMBIyiy6Gf0GsrZ0vQngXOdrNYbG4pxmQ== X-Received: by 2002:a1c:4c1a:: with SMTP id z26mr565803wmf.2.1564697270657; Thu, 01 Aug 2019 15:07:50 -0700 (PDT) Received: from vm-main.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id z19sm54128982wmi.7.2019.08.01.15.07.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Aug 2019 15:07:49 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Thu, 1 Aug 2019 15:07:30 -0700 Message-Id: <1564697253-37992-7-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> References: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 6/9] datapath: compat: Backport nf_conntrack_timeout support X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch brings in nf_ct_timeout_put() and nf_ct_set_timeout() when it is not available in the kernel. Three symbols are created in acinclude.m4. * HAVE_NF_CT_SET_TIMEOUT is used to determine if upstream net-next commit 717700d183d65 ("netfilter: Export nf_ct_{set,destroy}_timeout()") is availabe. If it is defined, the kernel should have all the nf_conntrack_timeout support that OVS needs. * HAVE_NF_CT_TIMEOUT is used to check if upstream net-next commit 6c1fd7dc489d9 ("netfilter: cttimeout: decouple timeout policy from nfnetlink_cttimeout object") is there. If it is not defined, we will use the old ctnl_timeout interface rather than the nf_ct_timeout interface that is introduced in this commit. * HAVE_NF_CT_TIMEOUT_FIND_GET_HOOK_NET is used to check if upstream commit 19576c9478682 ("netfilter: cttimeout: add netns support") is there, so that we pass different arguement based on whether the kernel has netns support. Signed-off-by: Yi-Hung Wei --- acinclude.m4 | 7 ++ datapath/linux/Modules.mk | 2 + .../include/net/netfilter/nf_conntrack_timeout.h | 34 +++++++ datapath/linux/compat/nf_conntrack_timeout.c | 102 +++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h create mode 100644 datapath/linux/compat/nf_conntrack_timeout.c diff --git a/acinclude.m4 b/acinclude.m4 index 9e1569b07c73..396b5f412094 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -707,6 +707,13 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_seqadj.h], [nf_ct_seq_adjust]) OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_count.h], [nf_conncount_gc_list], [OVS_DEFINE([HAVE_UPSTREAM_NF_CONNCOUNT])]) + OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_timeout.h], [nf_ct_set_timeout]) + OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_timeout.h], [struct nf_ct_timeout], + [OVS_DEFINE([HAVE_NF_CT_TIMEOUT])]) + OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_timeout.h], + [\(*nf_ct_timeout_find_get_hook\)], [net], + [OVS_DEFINE([HAVE_NF_CT_TIMEOUT_FIND_GET_HOOK_NET])]) + OVS_GREP_IFELSE([$KSRC/include/linux/random.h], [prandom_u32]) OVS_GREP_IFELSE([$KSRC/include/linux/random.h], [prandom_u32_max]) diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index cbb29f1c69d0..f93097b8e0e5 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -21,6 +21,7 @@ openvswitch_sources += \ linux/compat/nf_conntrack_core.c \ linux/compat/nf_conntrack_proto.c \ linux/compat/nf_conntrack_reasm.c \ + linux/compat/nf_conntrack_timeout.c \ linux/compat/reciprocal_div.c \ linux/compat/skbuff-openvswitch.c \ linux/compat/socket.c \ @@ -108,6 +109,7 @@ openvswitch_headers += \ linux/compat/include/net/netfilter/nf_conntrack_helper.h \ linux/compat/include/net/netfilter/nf_conntrack_labels.h \ linux/compat/include/net/netfilter/nf_conntrack_seqadj.h \ + linux/compat/include/net/netfilter/nf_conntrack_timeout.h \ linux/compat/include/net/netfilter/nf_conntrack_zones.h \ linux/compat/include/net/netfilter/nf_nat.h \ linux/compat/include/net/netfilter/ipv6/nf_defrag_ipv6.h \ diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h new file mode 100644 index 000000000000..134e72b8363e --- /dev/null +++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h @@ -0,0 +1,34 @@ +#ifndef _NF_CONNTRACK_TIMEOUT_WRAPPER_H +#define _NF_CONNTRACK_TIMEOUT_WRAPPER_H + +#include_next + +#ifndef HAVE_NF_CT_SET_TIMEOUT + +#ifndef HAVE_NF_CT_TIMEOUT +#define nf_ct_timeout ctnl_timeout +#endif + +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT +int rpl_nf_ct_set_timeout(struct net *net, struct nf_conn *ct, u8 l3num, u8 l4num, + const char *timeout_name); +void rpl_nf_ct_destroy_timeout(struct nf_conn *ct); +#else +static inline int rpl_nf_ct_set_timeout(struct net *net, struct nf_conn *ct, + u8 l3num, u8 l4num, + const char *timeout_name) +{ + return -EOPNOTSUPP; +} + +static inline void rpl_nf_ct_destroy_timeout(struct nf_conn *ct) +{ + return; +} +#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ + +#define nf_ct_set_timeout rpl_nf_ct_set_timeout +#define nf_ct_destroy_timeout rpl_nf_ct_destroy_timeout + +#endif /* HAVE_NF_CT_SET_TIMEOUT */ +#endif /* _NF_CONNTRACK_TIMEOUT_WRAPPER_H */ diff --git a/datapath/linux/compat/nf_conntrack_timeout.c b/datapath/linux/compat/nf_conntrack_timeout.c new file mode 100644 index 000000000000..c02baff5771b --- /dev/null +++ b/datapath/linux/compat/nf_conntrack_timeout.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include + +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT +#ifndef HAVE_NF_CT_SET_TIMEOUT +static void rpl__nf_ct_timeout_put(struct nf_ct_timeout *timeout) +{ + typeof(nf_ct_timeout_put_hook) timeout_put; + + timeout_put = rcu_dereference(nf_ct_timeout_put_hook); + if (timeout_put) + timeout_put(timeout); +} + +int rpl_nf_ct_set_timeout(struct net *net, struct nf_conn *ct, + u8 l3num, u8 l4num, const char *timeout_name) +{ + typeof(nf_ct_timeout_find_get_hook) timeout_find_get; + struct nf_ct_timeout *timeout; + struct nf_conn_timeout *timeout_ext; + const char *errmsg = NULL; + int ret = 0; + + rcu_read_lock(); + timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); + if (!timeout_find_get) { + ret = -ENOENT; + errmsg = "Timeout policy base is empty"; + goto out; + } + +#ifdef HAVE_NF_CT_TIMEOUT_FIND_GET_HOOK_NET + timeout = timeout_find_get(net, timeout_name); +#else + timeout = timeout_find_get(timeout_name); +#endif + if (!timeout) { + ret = -ENOENT; + pr_info_ratelimited("No such timeout policy \"%s\"\n", + timeout_name); + goto out; + } + + if (timeout->l3num != l3num) { + ret = -EINVAL; + pr_info_ratelimited("Timeout policy `%s' can only be used by " + "L%d protocol number %d\n", + timeout_name, 3, timeout->l3num); + goto err_put_timeout; + } + /* Make sure the timeout policy matches any existing protocol tracker, + * otherwise default to generic. + */ + if (timeout->l4proto->l4proto != l4num) { + ret = -EINVAL; + pr_info_ratelimited("Timeout policy `%s' can only be used by " + "L%d protocol number %d\n", + timeout_name, 4, timeout->l4proto->l4proto); + goto err_put_timeout; + } + timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); + if (!timeout_ext) { + ret = -ENOMEM; + goto err_put_timeout; + } + + rcu_read_unlock(); + return ret; + +err_put_timeout: + rpl__nf_ct_timeout_put(timeout); +out: + rcu_read_unlock(); + if (errmsg) + pr_info_ratelimited("%s\n", errmsg); + return ret; +} +EXPORT_SYMBOL_GPL(rpl_nf_ct_set_timeout); + +void rpl_nf_ct_destroy_timeout(struct nf_conn *ct) +{ + struct nf_conn_timeout *timeout_ext; + typeof(nf_ct_timeout_put_hook) timeout_put; + + rcu_read_lock(); + timeout_put = rcu_dereference(nf_ct_timeout_put_hook); + + if (timeout_put) { + timeout_ext = nf_ct_timeout_find(ct); + if (timeout_ext) { + timeout_put(timeout_ext->timeout); + RCU_INIT_POINTER(timeout_ext->timeout, NULL); + } + } + rcu_read_unlock(); +} +EXPORT_SYMBOL_GPL(rpl_nf_ct_destroy_timeout); + +#endif /* HAVE_NF_CT_SET_TIMEOUT */ +#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ From patchwork Thu Aug 1 22:07:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 1140794 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tdqqMWFF"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4604Jh6jTqz9s3Z for ; Fri, 2 Aug 2019 08:11:48 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 037F91701; Thu, 1 Aug 2019 22:07:57 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id A8EFA1689 for ; Thu, 1 Aug 2019 22:07:55 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 3C12182B for ; Thu, 1 Aug 2019 22:07:54 +0000 (UTC) Received: by mail-wr1-f43.google.com with SMTP id f9so75116215wre.12 for ; Thu, 01 Aug 2019 15:07:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=A8L9182TgerUr6TVkr6ePfyOinwZJ2JU6eS/zvKBuL8=; b=tdqqMWFFmbj2XJ+vO2lBIDMbsU87gC0/ZB6Tn15JAAiX4Cbneqw2SkpuOHK8ocNyo8 eTMq/sZH+mw/bNSj0rOuq0QfeacPt+qkOH7s1BgFsDZNJQ+AsD2AjIo6lb1OosDmrAIq qWRtSSSRRDw1/IZOvdF3xYfsXfMQ6bjerhBT+/w2ldHzF8isZ/Q4M/kRiPWgKrTxZ5iw uxNXGp6xUNi1jE2MSjKs5qOvnUZjtgUFALagOpyKxL7VcS7EvSzHID3durQstL5RhoUB MymtTufF7GiuHoxyX7yTi/P5r7AIbyTp/1xghPc200tgM5Bj+QM8jQ2Yt1LXm0CyaxwN QN7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=A8L9182TgerUr6TVkr6ePfyOinwZJ2JU6eS/zvKBuL8=; b=NWwD0pHL1bmP8AN6an90ExOxXV4wSJk2/5KmgB2P3D8zQv82nlzCXH5Px6s4Ok5D+B tw7kyxRxUSHk50O404BsSk+NbbRDeu2j+BRKAvv9e3zvB9f5nNSIoha+HF0BmusAi7zf GiNAYZ87I35mjdeblswRy60mPng5J3jP7RWsa2kIGwhZaZgEE4eHuOGpv3iuyZvfXlcJ Xw28AHTe+iO7FG13e9X1WZygb4jeADk9ldmmjG0k85s/vUHfTzYMi0U66lVCJREoI2cV TG+2qvwqkYk5L/fcIJ+w7ipgnZwYVq9Zkr1Y/nrMIqsJqffLz68Bz6ZjxKI+UDR1XVuC VSLQ== X-Gm-Message-State: APjAAAWqZiGNwMmCt20jhJTtzipEJMPRzPSw4IelTzsEtz4+FhUzr+Br E3n6eKMbpXfBHa+BejNcWfuHllnv X-Google-Smtp-Source: APXvYqwZmPv9Eqs96Bf+GKUBOGpAu2SGNdXPkj8APvC43rQT/qSULySAF65w61ok1XS5DlOHrXZzjA== X-Received: by 2002:a5d:6287:: with SMTP id k7mr22941339wru.108.1564697272447; Thu, 01 Aug 2019 15:07:52 -0700 (PDT) Received: from vm-main.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id z19sm54128982wmi.7.2019.08.01.15.07.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Aug 2019 15:07:51 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Thu, 1 Aug 2019 15:07:31 -0700 Message-Id: <1564697253-37992-8-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> References: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 7/9] datapath: Add support for conntrack timeout policy X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch adds support for specifying a timeout policy for a connection in connection tracking system in kernel datapath. The timeout policy will be attached to a connection when the connection is committed to conntrack. This patch introduces a new odp field OVS_CT_ATTR_TIMEOUT in the ct action that specifies the timeout policy in the datapath. In the following patch, during the upcall process, the vswitchd will use the ct_zone to look up the corresponding timeout policy and fill OVS_CT_ATTR_TIMEOUT if it is available. The datapath code is from the following two net-next upstream commits. Upstream commit: commit 06bd2bdf19d2f3d22731625e1a47fa1dff5ac407 Author: Yi-Hung Wei Date: Tue Mar 26 11:31:14 2019 -0700 openvswitch: Add timeout support to ct action Add support for fine-grain timeout support to conntrack action. The new OVS_CT_ATTR_TIMEOUT attribute of the conntrack action specifies a timeout to be associated with this connection. If no timeout is specified, it acts as is, that is the default timeout for the connection will be automatically applied. Example usage: $ nfct timeout add timeout_1 inet tcp syn_sent 100 established 200 $ ovs-ofctl add-flow br0 in_port=1,ip,tcp,action=ct(commit,timeout=timeout_1) CC: Pravin Shelar CC: Pablo Neira Ayuso Signed-off-by: Yi-Hung Wei Acked-by: Pravin B Shelar Signed-off-by: David S. Miller commit 6d670497e01803b486aa72cc1a718401ab986896 Author: Dan Carpenter Date: Tue Apr 2 09:53:14 2019 +0300 openvswitch: use after free in __ovs_ct_free_action() We free "ct_info->ct" and then use it on the next line when we pass it to nf_ct_destroy_timeout(). This patch swaps the order to avoid the use after free. Fixes: 06bd2bdf19d2 ("openvswitch: Add timeout support to ct action") Signed-off-by: Dan Carpenter Acked-by: Yi-Hung Wei Signed-off-by: David S. Miller Signed-off-by: Yi-Hung Wei --- datapath/conntrack.c | 30 ++++++++++++++++++++++- datapath/linux/compat/include/linux/openvswitch.h | 4 +++ lib/dpif-netdev.c | 4 +++ lib/odp-util.c | 29 +++++++++++++++++++--- tests/odp.at | 1 + 5 files changed, 63 insertions(+), 5 deletions(-) diff --git a/datapath/conntrack.c b/datapath/conntrack.c index 292febb3c83e..f85d0a2572f6 100644 --- a/datapath/conntrack.c +++ b/datapath/conntrack.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,7 @@ struct ovs_conntrack_info { u32 eventmask; /* Mask of 1 << IPCT_*. */ struct md_mark mark; struct md_labels labels; + char timeout[CTNL_TIMEOUT_NAME_MAX]; #ifdef CONFIG_NF_NAT_NEEDED struct nf_nat_range2 range; /* Only present for SRC NAT and DST NAT. */ #endif @@ -1519,6 +1521,8 @@ static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = { #endif [OVS_CT_ATTR_EVENTMASK] = { .minlen = sizeof(u32), .maxlen = sizeof(u32) }, + [OVS_CT_ATTR_TIMEOUT] = { .minlen = 1, + .maxlen = CTNL_TIMEOUT_NAME_MAX }, }; static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, @@ -1604,6 +1608,15 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, info->have_eventmask = true; info->eventmask = nla_get_u32(a); break; +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT + case OVS_CT_ATTR_TIMEOUT: + memcpy(info->timeout, nla_data(a), nla_len(a)); + if (!memchr(info->timeout, '\0', nla_len(a))) { + OVS_NLERR(log, "Invalid conntrack helper"); + return -EINVAL; + } + break; +#endif default: OVS_NLERR(log, "Unknown conntrack attr (%d)", @@ -1685,6 +1698,14 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, OVS_NLERR(log, "Failed to allocate conntrack template"); return -ENOMEM; } + + if (ct_info.timeout[0]) { + if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto, + ct_info.timeout)) + pr_info_ratelimited("Failed to associated timeout " + "policy `%s'\n", ct_info.timeout); + } + if (helper) { err = ovs_ct_add_helper(&ct_info, helper, key, log); if (err) @@ -1809,6 +1830,10 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info, if (ct_info->have_eventmask && nla_put_u32(skb, OVS_CT_ATTR_EVENTMASK, ct_info->eventmask)) return -EMSGSIZE; + if (ct_info->timeout[0]) { + if (nla_put_string(skb, OVS_CT_ATTR_TIMEOUT, ct_info->timeout)) + return -EMSGSIZE; + } #ifdef CONFIG_NF_NAT_NEEDED if (ct_info->nat && !ovs_ct_nat_to_attr(ct_info, skb)) @@ -1830,8 +1855,11 @@ static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info) { if (ct_info->helper) nf_conntrack_helper_put(ct_info->helper); - if (ct_info->ct) + if (ct_info->ct) { + if (ct_info->timeout[0]) + nf_ct_destroy_timeout(ct_info->ct); nf_ct_tmpl_free(ct_info->ct); + } } #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT) diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 65a003a62cf5..7b16b1d5bfe0 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -801,6 +801,7 @@ struct ovs_action_push_tnl { * be received on NFNLGRP_CONNTRACK_NEW and NFNLGRP_CONNTRACK_DESTROY groups, * respectively. Remaining bits control the changes for which an event is * delivered on the NFNLGRP_CONNTRACK_UPDATE group. + * @OVS_CT_ATTR_TIMEOUT: Variable length string defining conntrack timeout. */ enum ovs_ct_attr { OVS_CT_ATTR_UNSPEC, @@ -813,6 +814,9 @@ enum ovs_ct_attr { OVS_CT_ATTR_NAT, /* Nested OVS_NAT_ATTR_* */ OVS_CT_ATTR_FORCE_COMMIT, /* No argument */ OVS_CT_ATTR_EVENTMASK, /* u32 mask of IPCT_* events. */ + OVS_CT_ATTR_TIMEOUT, /* Associate timeout with this connection for + * fine-grain timeout tuning. */ + __OVS_CT_ATTR_MAX }; diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 2079e368fb52..7240a3e6f3c8 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -7204,6 +7204,10 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_, /* Silently ignored, as userspace datapath does not generate * netlink events. */ break; + case OVS_CT_ATTR_TIMEOUT: + /* Userspace datapath does not support customized timeout + * policy yet. */ + break; case OVS_CT_ATTR_NAT: { const struct nlattr *b_nest; unsigned int left_nest; diff --git a/lib/odp-util.c b/lib/odp-util.c index 84ea4c148f11..28c3209031ce 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -930,6 +930,8 @@ static const struct nl_policy ovs_conntrack_policy[] = { [OVS_CT_ATTR_HELPER] = { .type = NL_A_STRING, .optional = true, .min_len = 1, .max_len = 16 }, [OVS_CT_ATTR_NAT] = { .type = NL_A_UNSPEC, .optional = true }, + [OVS_CT_ATTR_TIMEOUT] = { .type = NL_A_STRING, .optional = true, + .min_len = 1, .max_len = 32 }, }; static void @@ -941,7 +943,7 @@ format_odp_conntrack_action(struct ds *ds, const struct nlattr *attr) ovs_32aligned_u128 mask; } *label; const uint32_t *mark; - const char *helper; + const char *helper, *timeout; uint16_t zone; bool commit, force; const struct nlattr *nat; @@ -957,10 +959,12 @@ format_odp_conntrack_action(struct ds *ds, const struct nlattr *attr) mark = a[OVS_CT_ATTR_MARK] ? nl_attr_get(a[OVS_CT_ATTR_MARK]) : NULL; label = a[OVS_CT_ATTR_LABELS] ? nl_attr_get(a[OVS_CT_ATTR_LABELS]): NULL; helper = a[OVS_CT_ATTR_HELPER] ? nl_attr_get(a[OVS_CT_ATTR_HELPER]) : NULL; + timeout = a[OVS_CT_ATTR_TIMEOUT] ? + nl_attr_get(a[OVS_CT_ATTR_TIMEOUT]) : NULL; nat = a[OVS_CT_ATTR_NAT]; ds_put_format(ds, "ct"); - if (commit || force || zone || mark || label || helper || nat) { + if (commit || force || zone || mark || label || helper || timeout || nat) { ds_put_cstr(ds, "("); if (commit) { ds_put_format(ds, "commit,"); @@ -983,6 +987,9 @@ format_odp_conntrack_action(struct ds *ds, const struct nlattr *attr) if (helper) { ds_put_format(ds, "helper=%s,", helper); } + if (timeout) { + ds_put_format(ds, "timeout=%s", timeout); + } if (nat) { format_odp_ct_nat(ds, nat); } @@ -1909,8 +1916,8 @@ parse_conntrack_action(const char *s_, struct ofpbuf *actions) const char *s = s_; if (ovs_scan(s, "ct")) { - const char *helper = NULL; - size_t helper_len = 0; + const char *helper = NULL, *timeout = NULL; + size_t helper_len = 0, timeout_len = 0; bool commit = false; bool force_commit = false; uint16_t zone = 0; @@ -1987,6 +1994,16 @@ find_end: s += helper_len; continue; } + if (ovs_scan(s, "timeout=%n", &n)) { + s += n; + timeout_len = strcspn(s, delimiters_end); + if (!timeout_len || timeout_len > 31) { + return -EINVAL; + } + timeout = s; + s += timeout_len; + continue; + } n = scan_ct_nat(s, &nat_params); if (n > 0) { @@ -2027,6 +2044,10 @@ find_end: nl_msg_put_string__(actions, OVS_CT_ATTR_HELPER, helper, helper_len); } + if (timeout) { + nl_msg_put_string__(actions, OVS_CT_ATTR_TIMEOUT, timeout, + timeout_len); + } if (have_nat) { nl_msg_put_ct_nat(&nat_params, actions); } diff --git a/tests/odp.at b/tests/odp.at index 8e4ba4615548..3ab9ad62dda2 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -345,6 +345,7 @@ ct(commit,mark=0xa0a0a0a0/0xfefefefe) ct(commit,label=0x1234567890abcdef1234567890abcdef/0xf1f2f3f4f5f6f7f8f9f0fafbfcfdfeff) ct(commit,helper=ftp) ct(commit,helper=tftp) +ct(commit,timeout=ovs_tp_1_tcp4) ct(nat) ct(commit,nat(src)) ct(commit,nat(dst)) From patchwork Thu Aug 1 22:07:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 1140795 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="blN6msew"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4604KB2hHnz9s3Z for ; Fri, 2 Aug 2019 08:12:14 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id DA42B1777; Thu, 1 Aug 2019 22:07:58 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 327581755 for ; Thu, 1 Aug 2019 22:07:57 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id E2A278AF for ; Thu, 1 Aug 2019 22:07:55 +0000 (UTC) Received: by mail-wr1-f67.google.com with SMTP id x4so21984141wrt.6 for ; Thu, 01 Aug 2019 15:07:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=lvE5owE3Lge/8djZ22Ix61iWvRaEFzl1PQLinlfRaqo=; b=blN6msew0iVHdqCAujc5xu6VdBPQJZkHT7SZY5iucd8zBy5I8nsTq53G3DezGssbFd BQNviyKMB0o/XZwvTFfZ21RUgYC0dMzN7WKVCdh7ipMY299uN5Xk13EXn2uWYFzmtTDf UhYl/gn5egKVt4r0U1vsoskYIMp2Am2yB84Xbad3rVvjqfwSa4LUnCKyxeODxrkNy9BH QfUYm3Xrs98DwvLFq6KLrGq4YlLSeJQHkcga2v8gkC9QhJu/qdH3J1IFYRP5OzI9quNh JBFz1AqUi2lKp3Nw5EDL8vGbi8sJHpIqXKW24xqAE13BYGz2clvQ6kc4eT5OxJKqmwQB AaTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=lvE5owE3Lge/8djZ22Ix61iWvRaEFzl1PQLinlfRaqo=; b=owkYu+Zh/tj8p1teoqZqA7hgAejRDX3Pnatru6xvrn6OzNs3bS5rinigWbeYn7tgy7 gerD/tQcN8oCS+pS5naL0+xjoEozg8asA2PYFsq8Y3fxZTWhKy73gmQOTBzno+qnUrnC TAxDIr6IHGSX9756yWG4YqzVBsfP0rUE1cstrgKlBWWp9752vpQTtxHjgEsosL16EXP4 9ntHAe6syDuNsO9lxKy/EQlxWGxqJjY3Oti89qQdRRkmNVVgh+mobTGxQP/fE1lXgy+4 Oo6BFdfbvXAh9GmexQxsB5hlEf2OQxLWJtHtdgOOmtmhV93e6JNlbLe5LnFHMKPX7I8L BQrA== X-Gm-Message-State: APjAAAUoyWfM8ncD1VKVzvC+OJ446mp+tKEwyX4TbQ7/cDler9G/J1rD /C2J10apVBa5tRiFi8SYRA4qGTcU X-Google-Smtp-Source: APXvYqxkgFBwNWAAPY/YweJlvp+t6RL+b+7D+xdY8IQRLmivAd3eiXkqJ077J9Xn8JKjpjj66OPwaw== X-Received: by 2002:adf:cd84:: with SMTP id q4mr64910241wrj.232.1564697274116; Thu, 01 Aug 2019 15:07:54 -0700 (PDT) Received: from vm-main.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id z19sm54128982wmi.7.2019.08.01.15.07.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Aug 2019 15:07:53 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Thu, 1 Aug 2019 15:07:32 -0700 Message-Id: <1564697253-37992-9-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> References: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 8/9] ofproto-dpif-xlate: Translate timeout policy in ct action X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch derives the timeout policy based on ct zone from the internal data structure that reads the configuration from ovsdb. Signed-off-by: Yi-Hung Wei --- lib/ct-dpif.c | 10 ++++++++++ lib/ct-dpif.h | 3 +++ lib/dpif-netdev.c | 1 + lib/dpif-netlink.c | 10 ++++++++++ lib/dpif-provider.h | 5 +++++ ofproto/ofproto-dpif-xlate.c | 29 +++++++++++++++++++++++++++++ ofproto/ofproto-dpif.c | 24 ++++++++++++++++++++++++ ofproto/ofproto-provider.h | 5 +++++ ofproto/ofproto.c | 11 +++++++++++ ofproto/ofproto.h | 2 ++ 10 files changed, 100 insertions(+) diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c index 7f9ce0a561f7..5d2acfd7810b 100644 --- a/lib/ct-dpif.c +++ b/lib/ct-dpif.c @@ -864,3 +864,13 @@ ct_dpif_timeout_policy_dump_done(struct dpif *dpif, void *state) ? dpif->dpif_class->ct_timeout_policy_dump_done(dpif, state) : EOPNOTSUPP); } + +int +ct_dpif_format_timeout_policy_name(struct dpif *dpif, uint32_t tp_id, + uint16_t dl_type, uint8_t nw_proto, + struct ds *ds) +{ + return (dpif->dpif_class->ct_format_timeout_policy_name + ? dpif->dpif_class->ct_format_timeout_policy_name( + dpif, tp_id, dl_type, nw_proto, ds) : EOPNOTSUPP); +} diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h index 8dacb1c7c253..0a27568880c0 100644 --- a/lib/ct-dpif.h +++ b/lib/ct-dpif.h @@ -318,5 +318,8 @@ int ct_dpif_timeout_policy_dump_start(struct dpif *dpif, void **statep); int ct_dpif_timeout_policy_dump_next(struct dpif *dpif, void *state, struct ct_dpif_timeout_policy *tp); int ct_dpif_timeout_policy_dump_done(struct dpif *dpif, void *state); +int ct_dpif_format_timeout_policy_name(struct dpif *dpif, uint32_t tp_id, + uint16_t dl_type, uint8_t nw_proto, + struct ds *ds); #endif /* CT_DPIF_H */ diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 7240a3e6f3c8..19cf9f21ec85 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -7539,6 +7539,7 @@ const struct dpif_class dpif_netdev_class = { NULL, /* ct_timeout_policy_dump_start */ NULL, /* ct_timeout_policy_dump_next */ NULL, /* ct_timeout_policy_dump_done */ + NULL, /* ct_format_timeout_policy_name */ dpif_netdev_ipf_set_enabled, dpif_netdev_ipf_set_min_frag, dpif_netdev_ipf_set_max_nfrags, diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index b859508f718a..92da87027c58 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -3071,6 +3071,15 @@ dpif_netlink_format_tp_name(uint32_t id, uint16_t l3num, uint8_t l4num, ovs_assert(tp_name->length < CTNL_TIMEOUT_NAME_MAX); } +static int +dpif_netlink_ct_format_timeout_policy_name(struct dpif *dpif OVS_UNUSED, + uint32_t tp_id, uint16_t dl_type, uint8_t nw_proto, struct ds *ds) +{ + dpif_netlink_format_tp_name(tp_id, + dl_type == ETH_TYPE_IP ? AF_INET : AF_INET6, nw_proto, ds); + return 0; +} + #define CT_DPIF_NL_TP_TCP_MAPPINGS \ CT_DPIF_NL_TP_MAPPING(TCP, TCP, SYN_SENT, SYN_SENT) \ CT_DPIF_NL_TP_MAPPING(TCP, TCP, SYN_RECV, SYN_RECV) \ @@ -3891,6 +3900,7 @@ const struct dpif_class dpif_netlink_class = { dpif_netlink_ct_timeout_policy_dump_start, dpif_netlink_ct_timeout_policy_dump_next, dpif_netlink_ct_timeout_policy_dump_done, + dpif_netlink_ct_format_timeout_policy_name, NULL, /* ipf_set_enabled */ NULL, /* ipf_set_min_frag */ NULL, /* ipf_set_max_nfrags */ diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index 79a2314500cf..57b32ccb610f 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -536,6 +536,11 @@ struct dpif_class { struct ct_dpif_timeout_policy *tp); int (*ct_timeout_policy_dump_done)(struct dpif *, void *state); + /* Get timeout policy name (OVS_CT_ATTR_TIMEOUT) from datapath. */ + int (*ct_format_timeout_policy_name)(struct dpif *, uint32_t tp_id, + uint16_t dl_type, uint8_t nw_proto, + struct ds *ds); + /* IP Fragmentation. */ /* Disables or enables conntrack fragment reassembly. The default diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 28a7fdd842a6..f9b517aaa270 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -28,6 +28,7 @@ #include "bond.h" #include "bundle.h" #include "byte-order.h" +#include "ct-dpif.h" #include "cfm.h" #include "connmgr.h" #include "coverage.h" @@ -5977,6 +5978,30 @@ put_ct_helper(struct xlate_ctx *ctx, } static void +put_ct_timeout(struct ofpbuf *odp_actions, const char *dp_type, + const struct ofproto_dpif *ofproto, const struct flow *flow, + struct flow_wildcards *wc, uint16_t zone_id) +{ + struct dpif_backer *backer = ofproto->backer; + uint32_t tp_id; + + if (ofproto_ct_zone_timeout_policy_get(&ofproto->up, zone_id, &tp_id)) { + if (!strcmp(dp_type, "system")) { + struct ds ds = DS_EMPTY_INITIALIZER; + int err = ct_dpif_format_timeout_policy_name( + backer->dpif, tp_id, ntohs(flow->dl_type), + flow->nw_proto, &ds); + if (!err) { + memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); + nl_msg_put_string(odp_actions, OVS_CT_ATTR_TIMEOUT, + ds_cstr(&ds)); + } + ds_destroy(&ds); + } + } +} + +static void put_ct_nat(struct xlate_ctx *ctx) { struct ofpact_nat *ofn = ctx->ct_nat_action; @@ -6071,6 +6096,10 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc, put_ct_mark(&ctx->xin->flow, ctx->odp_actions, ctx->wc); put_ct_label(&ctx->xin->flow, ctx->odp_actions, ctx->wc); put_ct_helper(ctx, ctx->odp_actions, ofc); + if (ofc->flags & NX_CT_F_COMMIT) { + put_ct_timeout(ctx->odp_actions, ctx->xbridge->ofproto->backer->type, + ctx->xbridge->ofproto, &ctx->xin->flow, ctx->wc, zone); + } put_ct_nat(ctx); ctx->ct_nat_action = NULL; nl_msg_end_nested(ctx->odp_actions, ct_offset); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 6336494e0bc8..f31162f4481d 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -5351,6 +5351,29 @@ ct_zone_timeout_policy_reconfig(const struct ofproto *ofproto, } static bool +ct_zone_timeout_policy_get(const struct ofproto *ofproto_, + uint16_t zone, uint32_t *tp_id) +{ + struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); + struct dpif_backer *backer = ofproto->backer; + struct ct_zone *ct_zone; + struct ct_timeout_policy *ct_tp; + + ct_zone = ct_zone_lookup(&backer->ct_zones, zone); + if (!ct_zone) { + return false; + } + + ct_tp = ct_timeout_policy_lookup(&backer->ct_tps, &ct_zone->tp_uuid); + if (!ct_tp) { + return false; + } + + *tp_id = ct_tp->cdtp.id; + return true; +} + +static bool set_frag_handling(struct ofproto *ofproto_, enum ofputil_frag_handling frag_handling) { @@ -6455,4 +6478,5 @@ const struct ofproto_class ofproto_dpif_class = { ct_flush, /* ct_flush */ ct_zone_timeout_policy_reconfig, ct_zone_timeout_policy_sweep, + ct_zone_timeout_policy_get, }; diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 41e07f0ee23e..1a2fc4a6a084 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1880,6 +1880,11 @@ struct ofproto_class { const struct ovsrec_datapath *dp_cfg, unsigned int idl_seqno); /* Cleans up the to be deleted timeout policy in the pending kill list. */ void (*ct_zone_timeout_policy_sweep)(const struct ofproto *ofproto_); + + /* Returns true if timeout policy for 'zone' is configured and stores the + * timeout policy id in '*tp_id'. */ + bool (*ct_zone_timeout_policy_get)(const struct ofproto *ofproto_, + uint16_t zone, uint32_t *tp_id); }; extern const struct ofproto_class ofproto_dpif_class; diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 373b8a4eba0c..cef0690cf466 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -955,6 +955,17 @@ ofproto_ct_zone_timeout_policy_sweep(const struct ofproto *ofproto) } } +bool +ofproto_ct_zone_timeout_policy_get(const struct ofproto *ofproto, + uint16_t zone, uint32_t *tp_id) +{ + if (ofproto->ofproto_class->ct_zone_timeout_policy_get) { + return ofproto->ofproto_class->ct_zone_timeout_policy_get( + ofproto, zone, tp_id); + } + return false; +} + /* Spanning Tree Protocol (STP) configuration. */ diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 2ae42374be36..8749cabdb7bd 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -366,6 +366,8 @@ void ofproto_set_vlan_limit(int vlan_limit); void ofproto_ct_zone_timeout_policy_reconfig(const struct ofproto *ofproto, const struct ovsrec_datapath *dp_cfg, unsigned int idl_seqno); void ofproto_ct_zone_timeout_policy_sweep(const struct ofproto *ofproto); +bool ofproto_ct_zone_timeout_policy_get(const struct ofproto *ofproto, + uint16_t zone, uint32_t *tp_id); /* Configuration of ports. */ void ofproto_port_unregister(struct ofproto *, ofp_port_t ofp_port); From patchwork Thu Aug 1 22:07:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 1140796 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="FLJ2kir/"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4604Ks0L8Sz9s3Z for ; Fri, 2 Aug 2019 08:12:49 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id EF78717F5; Thu, 1 Aug 2019 22:08:00 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id E323D177B for ; Thu, 1 Aug 2019 22:07:58 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wm1-f65.google.com (mail-wm1-f65.google.com [209.85.128.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 76A798AD for ; Thu, 1 Aug 2019 22:07:57 +0000 (UTC) Received: by mail-wm1-f65.google.com with SMTP id u25so54152764wmc.4 for ; Thu, 01 Aug 2019 15:07:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+PLRg8cWt/KGYrf5ziOn9IZakvQjpAkixDH/f5tHstk=; b=FLJ2kir/VaoAngVLGx8M6jv/IuMxcnIy2HaT0a1MbVrnVZodddpnvRvpzmr2FdNKOK vNSTAacqR8D8akbP9vM9uYyZMSiFnwOurjeJnxopm1Tmsx1rBubNkWbqaonGn+4P7mGL Ze6A8qhBpunlNJRAEcC3LzGJym4iVqi1pDN2su+2aG6uUOnjUfUiq1XrfSHysJNQmTyf YwJrkVzxGm5CPy3QxyJcbFPWElHv/LXmrSfQSnWMswh93VFZUHZB4OeUr1ggempfskPh ltqMlOPu3evRDGiqD+ufH0p9Aruzjnd4Z5UaDr2vXeEiPI7mtgkw8scQVGM6D5gq9Cwu TtbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+PLRg8cWt/KGYrf5ziOn9IZakvQjpAkixDH/f5tHstk=; b=ZO3ZjTPUZPTIvjdHG13TG2k733S6i9tgCLo3dL6wopw2wc/qxgZFVLAkNAmlqsATCx XogkQjJ3bDj28QIkCX1pKa2nx8cCKELVY4fJMx5KBK0KDd/ubcVpiYUGiI5FllXxetxe kqHNoldtzy3A4IR+f01K8N060XGE0/JAwO6wWu0IwYnNXyK/GM581PmnoK0cQITD+RBS JVHBmonM3x1Z0t1BdLrwrfcCr2ebyooeqTsD7Ktg9Xqc986AlUXUN1d/uXdloDOBzLbn mw7sto3xMS7DmDDCOU4MF1bIjO/QvT+mWfUkGu8Qbl/pLiRwgagNmpR5oFbbdV5KeyW+ U7HA== X-Gm-Message-State: APjAAAV9Mk0+zlerdTQmnRc62vzix1jN0mh19kqhgWkSi3lv0Harcrll 4orcKqEsLDgZoV0TdeSbprU2e4vX X-Google-Smtp-Source: APXvYqxa7hzo5CJGX9DdYyHRoWWTgF8ntsMs7JOUXEprdxUqbD7f5Ad7thUNlhyN0+ZlyYVIn7OqEA== X-Received: by 2002:a1c:f70c:: with SMTP id v12mr568771wmh.42.1564697275763; Thu, 01 Aug 2019 15:07:55 -0700 (PDT) Received: from vm-main.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id z19sm54128982wmi.7.2019.08.01.15.07.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Aug 2019 15:07:55 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Thu, 1 Aug 2019 15:07:33 -0700 Message-Id: <1564697253-37992-10-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> References: <1564697253-37992-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 9/9] system-traffic: Add zone-based conntrack timeout policy test X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch adds a system traffic test to verify the zone-based conntrack timeout feature. The test uses ovs-vsctl commands to configure the customized ICMP and UDP timeout on zone 5 to a shorter period. It then injects ICMP and UDP traffic to conntrack, and checks if the corresponding conntrack entry expires after the predefined timeout. Signed-off-by: Yi-Hung Wei --- tests/system-kmod-macros.at | 25 +++++++++++++++ tests/system-traffic.at | 66 ++++++++++++++++++++++++++++++++++++++++ tests/system-userspace-macros.at | 26 ++++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at index 554a61e9bd95..1bc6f246f426 100644 --- a/tests/system-kmod-macros.at +++ b/tests/system-kmod-macros.at @@ -100,6 +100,15 @@ m4_define([CHECK_CONNTRACK_FRAG_OVERLAP], # m4_define([CHECK_CONNTRACK_NAT]) +# CHECK_CONNTRACK_TIMEOUT() +# +# Perform requirements checks for running conntrack customized timeout tests. +# +m4_define([CHECK_CONNTRACK_TIMEOUT], +[ + AT_SKIP_IF([! cat /boot/config-$(uname -r) | grep NF_CONNTRACK_TIMEOUT | grep '=y' > /dev/null]) +]) + # CHECK_CT_DPIF_PER_ZONE_LIMIT() # # Perform requirements checks for running ovs-dpctl ct-[set|get|del]-limits per @@ -185,3 +194,19 @@ m4_define([OVS_CHECK_KERNEL_EXCL], sublevel=$(uname -r | sed -e 's/\./ /g' | awk '{print $ 2}') AT_SKIP_IF([ ! ( test $version -lt $1 || ( test $version -eq $1 && test $sublevel -lt $2 ) || test $version -gt $3 || ( test $version -eq $3 && test $sublevel -gt $4 ) ) ]) ]) + +# VSCTL_ADD_DATAPATH_TABLE() +# +# Create system datapath table "system" for kernel tests in ovsdb +m4_define([VSCTL_ADD_DATAPATH_TABLE], +[ + AT_CHECK([ovs-vsctl -- --id=@m create Datapath datapath_version=0 -- set Open_vSwitch . datapaths:"system"=@m], [0], [stdout]) +]) + +# VSCTL_ADD_ZONE_TIMEOUT_POLICY([parameters]) +# +# Add zone based timeout policy to kernel datapath +m4_define([VSCTL_ADD_ZONE_TIMEOUT_POLICY], +[ + AT_CHECK([ovs-vsctl add-zone-tp system $1], [0], [stdout]) +]) diff --git a/tests/system-traffic.at b/tests/system-traffic.at index 1a04199dcfe9..f4ac8a8f2c06 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -3179,6 +3179,72 @@ NXST_FLOW reply: OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([conntrack - zone-based timeout policy]) +CHECK_CONNTRACK() +CHECK_CONNTRACK_TIMEOUT() +OVS_TRAFFIC_VSWITCHD_START() + +ADD_NAMESPACES(at_ns0, at_ns1) + +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") + +AT_DATA([flows.txt], [dnl +priority=1,action=drop +priority=10,arp,action=normal +priority=100,in_port=1,ip,action=ct(zone=5, table=1) +priority=100,in_port=2,ip,action=ct(zone=5, table=1) +table=1,in_port=2,ip,ct_state=+trk+est,action=1 +table=1,in_port=1,ip,ct_state=+trk+new,action=ct(commit,zone=5),2 +table=1,in_port=1,ip,ct_state=+trk+est,action=2 +]) + +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt]) + +dnl Test with default timeout +dnl The default udp_single and icmp_first timeouts are 30 seconds in +dnl kernel DP, and 60 seconds in userspace DP. + +dnl Send ICMP and UDP traffic +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.2 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000200080000 actions=resubmit(,0)"]) + +sleep 4 + +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | sort], [0], [dnl +icmp,orig=(src=10.1.1.1,dst=10.1.1.2,id=,type=8,code=0),reply=(src=10.1.1.2,dst=10.1.1.1,id=,type=0,code=0),zone=5 +udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),reply=(src=10.1.1.2,dst=10.1.1.1,sport=,dport=),zone=5 +]) + +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) + +dnl Shorten the udp_single and icmp_first timeout in zone 5 +VSCTL_ADD_DATAPATH_TABLE() +VSCTL_ADD_ZONE_TIMEOUT_POLICY([zone=5 udp_single=3 icmp_first=3]) + +dnl Send ICMP and UDP traffic +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.2 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000200080000 actions=resubmit(,0)"]) + +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | sort], [0], [dnl +icmp,orig=(src=10.1.1.1,dst=10.1.1.2,id=,type=8,code=0),reply=(src=10.1.1.2,dst=10.1.1.1,id=,type=0,code=0),zone=5 +udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),reply=(src=10.1.1.2,dst=10.1.1.1,sport=,dport=),zone=5 +]) + +dnl Wait until the timeout expire. +dnl We intend to wait a bit longer, because conntrack does not recycle the entry right after it is expired. +sleep 4 + +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl +]) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + AT_BANNER([conntrack - L7]) AT_SETUP([conntrack - IPv4 HTTP]) diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at index 9d5f3bf419d3..8950a4de7287 100644 --- a/tests/system-userspace-macros.at +++ b/tests/system-userspace-macros.at @@ -98,6 +98,16 @@ m4_define([CHECK_CONNTRACK_FRAG_OVERLAP]) # m4_define([CHECK_CONNTRACK_NAT]) +# CHECK_CONNTRACK_TIMEOUT() +# +# Perform requirements checks for running conntrack customized timeout tests. +* The userspace datapath does not support this feature yet. +# +m4_define([CHECK_CONNTRACK_TIMEOUT], +[ + AT_SKIP_IF([:]) +]) + # CHECK_CT_DPIF_PER_ZONE_LIMIT() # # Perform requirements checks for running ovs-dpctl ct-[set|get|del]-limits per @@ -295,3 +305,19 @@ m4_define([OVS_CHECK_KERNEL_EXCL], [ AT_SKIP_IF([:]) ]) + +# VSCTL_ADD_DATAPATH_TABLE() +# +# Create datapath table "netdev" for userspace tests in ovsdb +m4_define([VSCTL_ADD_DATAPATH_TABLE], +[ + AT_CHECK([ovs-vsctl -- --id=@m create Datapath datapath_version=0 -- set Open_vSwitch . datapaths:"netdev"=@m], [0], [stdout]) +]) + +# VSCTL_ADD_ZONE_TIMEOUT_POLICY([parameters]) +# +# Add zone based timeout policy to userspace datapath +m4_define([VSCTL_ADD_ZONE_TIMEOUT_POLICY], +[ + AT_CHECK([ovs-vsctl add-zone-tp netdev $1], [0], [stdout]) +])