From patchwork Tue May 21 18:16:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 1102946 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=redhat.com 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 457kVg0v9Fz9s9y for ; Wed, 22 May 2019 04:16:42 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id AE488C91; Tue, 21 May 2019 18:16:39 +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 C9F6DBDC for ; Tue, 21 May 2019 18:16:37 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 3AA0C81A for ; Tue, 21 May 2019 18:16:37 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 845C385A07; Tue, 21 May 2019 18:16:36 +0000 (UTC) Received: from dhcp-25.97.bos.redhat.com (unknown [10.18.25.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 04EAF5C69A; Tue, 21 May 2019 18:16:35 +0000 (UTC) From: Aaron Conole To: dev@openvswitch.org Date: Tue, 21 May 2019 14:16:31 -0400 Message-Id: <20190521181631.14687-2-aconole@redhat.com> In-Reply-To: <20190521181631.14687-1-aconole@redhat.com> References: <20190521181631.14687-1-aconole@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Tue, 21 May 2019 18:16:36 +0000 (UTC) X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 v3 2/2] conntrack: add display support for sctp 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: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Currently, only the netlink datapath supports SCTP connection tracking, but at least this removes the warning message that will pop up when running something like: ovs-appctl dpctl/dump-conntrack This doesn't impact any conntrack functionality, just the display. Signed-off-by: Aaron Conole --- v3: Moved the header detection to 1/2, and added a compat layer Changed to PRIu32 format specifier lib/ct-dpif.c | 19 +++++++++++ lib/ct-dpif.h | 25 +++++++++++++++ lib/netlink-conntrack.c | 70 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c index b2c9b4309..5d8a75d3a 100644 --- a/lib/ct-dpif.c +++ b/lib/ct-dpif.c @@ -428,6 +428,12 @@ const char *ct_dpif_tcp_state_string[] = { #undef CT_DPIF_TCP_STATE }; +const char *ct_dpif_sctp_state_string[] = { +#define CT_DPIF_SCTP_STATE(STATE) [CT_DPIF_SCTP_STATE_##STATE] = #STATE, + CT_DPIF_SCTP_STATES +#undef CT_DPIF_SCTP_STATE +}; + static void ct_dpif_format_enum__(struct ds *ds, const char *title, unsigned int state, const char *names[], unsigned int max) @@ -497,6 +503,16 @@ ct_dpif_format_protoinfo_tcp_verbose(struct ds *ds, tcp_flags); } +static void +ct_dpif_format_protoinfo_sctp(struct ds *ds, + const struct ct_dpif_protoinfo *protoinfo) +{ + ct_dpif_format_enum(ds, "state=", protoinfo->sctp.state, + ct_dpif_sctp_state_string); + ds_put_format(ds, ",vtag_orig=%" PRIu32 ",vtag_reply=%" PRIu32, + protoinfo->sctp.vtag_orig, protoinfo->sctp.vtag_reply); +} + static void ct_dpif_format_protoinfo(struct ds *ds, const char *title, const struct ct_dpif_protoinfo *protoinfo, @@ -514,6 +530,9 @@ ct_dpif_format_protoinfo(struct ds *ds, const char *title, ct_dpif_format_protoinfo_tcp(ds, protoinfo); } break; + case IPPROTO_SCTP: + ct_dpif_format_protoinfo_sctp(ds, protoinfo); + break; } if (title) { ds_put_cstr(ds, ")"); diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h index 2628c2b68..14178bb7c 100644 --- a/lib/ct-dpif.h +++ b/lib/ct-dpif.h @@ -101,6 +101,26 @@ enum ct_dpif_tcp_flags { #undef CT_DPIF_TCP_FLAG }; +extern const char *ct_dpif_sctp_state_string[]; + +#define CT_DPIF_SCTP_STATES \ + CT_DPIF_SCTP_STATE(CLOSED) \ + CT_DPIF_SCTP_STATE(COOKIE_WAIT) \ + CT_DPIF_SCTP_STATE(COOKIE_ECHOED) \ + CT_DPIF_SCTP_STATE(ESTABLISHED) \ + CT_DPIF_SCTP_STATE(SHUTDOWN_SENT) \ + CT_DPIF_SCTP_STATE(SHUTDOWN_RECD) \ + CT_DPIF_SCTP_STATE(SHUTDOWN_ACK_SENT) \ + CT_DPIF_SCTP_STATE(HEARTBEAT_SENT) \ + CT_DPIF_SCTP_STATE(HEARTBEAT_ACKED) \ + CT_DPIF_SCTP_STATE(MAX_NUM) + +enum ct_dpif_sctp_state { +#define CT_DPIF_SCTP_STATE(STATE) CT_DPIF_SCTP_STATE_##STATE, + CT_DPIF_SCTP_STATES +#undef CT_DPIF_SCTP_STATE +}; + struct ct_dpif_protoinfo { uint16_t proto; /* IPPROTO_* */ union { @@ -112,6 +132,11 @@ struct ct_dpif_protoinfo { uint8_t flags_orig; uint8_t flags_reply; } tcp; + struct { + uint8_t state; + uint32_t vtag_orig; + uint32_t vtag_reply; + } sctp; }; }; diff --git a/lib/netlink-conntrack.c b/lib/netlink-conntrack.c index 42be1d9ce..7631ba5d5 100644 --- a/lib/netlink-conntrack.c +++ b/lib/netlink-conntrack.c @@ -717,6 +717,73 @@ nl_ct_parse_protoinfo_tcp(struct nlattr *nla, return parsed; } +/* Translate netlink SCTP state to CT_DPIF_SCTP state. */ +static uint8_t +nl_ct_sctp_state_to_dpif(uint8_t state) +{ +#ifdef _WIN32 + /* For now, return the CT_DPIF_SCTP state. Not sure what windows does. */ + return state; +#else + switch (state) { + case SCTP_CONNTRACK_COOKIE_WAIT: + return CT_DPIF_SCTP_STATE_COOKIE_WAIT; + case SCTP_CONNTRACK_COOKIE_ECHOED: + return CT_DPIF_SCTP_STATE_COOKIE_ECHOED; + case SCTP_CONNTRACK_ESTABLISHED: + return CT_DPIF_SCTP_STATE_ESTABLISHED; + case SCTP_CONNTRACK_SHUTDOWN_SENT: + return CT_DPIF_SCTP_STATE_SHUTDOWN_SENT; + case SCTP_CONNTRACK_SHUTDOWN_RECD: + return CT_DPIF_SCTP_STATE_SHUTDOWN_RECD; + case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT: + return CT_DPIF_SCTP_STATE_SHUTDOWN_ACK_SENT; + case SCTP_CONNTRACK_HEARTBEAT_SENT: + return CT_DPIF_SCTP_STATE_HEARTBEAT_SENT; + case SCTP_CONNTRACK_HEARTBEAT_ACKED: + return CT_DPIF_SCTP_STATE_HEARTBEAT_ACKED; + case SCTP_CONNTRACK_CLOSED: + /* Fall Through. */ + case SCTP_CONNTRACK_NONE: + /* Fall Through. */ + default: + return CT_DPIF_SCTP_STATE_CLOSED; + } +#endif +} + +static bool +nl_ct_parse_protoinfo_sctp(struct nlattr *nla, + struct ct_dpif_protoinfo *protoinfo) +{ + static const struct nl_policy policy[] = { + [CTA_PROTOINFO_SCTP_STATE] = { .type = NL_A_U8, .optional = false }, + [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NL_A_U32, + .optional = false }, + [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NL_A_U32, + .optional = false }, + }; + struct nlattr *attrs[ARRAY_SIZE(policy)]; + bool parsed; + + parsed = nl_parse_nested(nla, policy, attrs, ARRAY_SIZE(policy)); + if (parsed) { + protoinfo->proto = IPPROTO_SCTP; + + protoinfo->sctp.state = nl_ct_sctp_state_to_dpif( + nl_attr_get_u8(attrs[CTA_PROTOINFO_SCTP_STATE])); + protoinfo->sctp.vtag_orig = nl_attr_get_u32( + attrs[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]); + protoinfo->sctp.vtag_reply = nl_attr_get_u32( + attrs[CTA_PROTOINFO_SCTP_VTAG_REPLY]); + } else { + VLOG_ERR_RL(&rl, "Could not parse nested SCTP protoinfo options. " + "Possibly incompatible Linux kernel version."); + } + + return parsed; +} + static bool nl_ct_parse_protoinfo(struct nlattr *nla, struct ct_dpif_protoinfo *protoinfo) { @@ -737,7 +804,8 @@ nl_ct_parse_protoinfo(struct nlattr *nla, struct ct_dpif_protoinfo *protoinfo) parsed = nl_ct_parse_protoinfo_tcp(attrs[CTA_PROTOINFO_TCP], protoinfo); } else if (attrs[CTA_PROTOINFO_SCTP]) { - VLOG_WARN_RL(&rl, "SCTP protoinfo not yet supported!"); + parsed = nl_ct_parse_protoinfo_sctp(attrs[CTA_PROTOINFO_SCTP], + protoinfo); } else { VLOG_WARN_RL(&rl, "Empty protoinfo!"); }