From patchwork Fri May 17 16:04:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 1101139 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 455Clq3Fl2z9s9N for ; Sat, 18 May 2019 02:04:22 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 3C504B8A; Fri, 17 May 2019 16:04:18 +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 B398EB88 for ; Fri, 17 May 2019 16:04:17 +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 93F5684F for ; Fri, 17 May 2019 16:04:14 +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 EED1830C0DD7; Fri, 17 May 2019 16:04:03 +0000 (UTC) Received: from dhcp-25.97.bos.redhat.com (unknown [10.18.25.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9798A5C1B5; Fri, 17 May 2019 16:04:03 +0000 (UTC) From: Aaron Conole To: dev@openvswitch.org Date: Fri, 17 May 2019 12:04:02 -0400 Message-Id: <20190517160402.28095-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.45]); Fri, 17 May 2019 16:04:04 +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] 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 --- I did the heartbeat states by hardcoding the values in the ENUM since they are fixed in the linux UAPI, and have existed for a long time, but it could also make sense to rework this patch so that those states are omitted by the ifdef rather than defining them (I'll submit a v2 if that's preferred approach - but this seems like the more flexible option). acinclude.m4 | 12 +++++++ configure.ac | 1 + lib/ct-dpif.c | 19 +++++++++++ lib/ct-dpif.h | 30 ++++++++++++++++++ lib/netlink-conntrack.c | 70 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 131 insertions(+), 1 deletion(-) diff --git a/acinclude.m4 b/acinclude.m4 index b532a4579..ca770ec81 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -212,6 +212,18 @@ AC_DEFUN([OVS_CHECK_LINUX_TC], [ [Define to 1 if TCA_SKBEDIT_FLAGS is available.])]) ]) +dnl OVS_CHECK_LINUX_SCTP_CT +dnl +dnl Checks for kernels which need additional SCTP state +AC_DEFUN([OVS_CHECK_LINUX_SCTP_CT], [ + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([#include 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 0151cfea4..34e41ed30 100644 --- a/lib/ct-dpif.h +++ b/lib/ct-dpif.h @@ -101,6 +101,31 @@ enum ct_dpif_tcp_flags { #undef CT_DPIF_TCP_FLAG }; +#ifndef HAVE_SCTP_CONNTRACK_HEARTBEATS +#define SCTP_CONNTRACK_HEARTBEAT_SENT SCTP_CONNTRACK_SHUTDOWN_ACK_SENT+1 +#define SCTP_CONNTRACK_HEARTBEAT_ACKED SCTP_CONNTRACK_SHUTDOWN_ACK_SENT+2 +#endif + +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 +137,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!"); }