From patchwork Tue Feb 26 14:36:13 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Roberts, Lee A." X-Patchwork-Id: 223230 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 501FF2C0292 for ; Wed, 27 Feb 2013 01:35:39 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759385Ab3BZOff (ORCPT ); Tue, 26 Feb 2013 09:35:35 -0500 Received: from g1t0027.austin.hp.com ([15.216.28.34]:46565 "EHLO g1t0027.austin.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758153Ab3BZOf1 (ORCPT ); Tue, 26 Feb 2013 09:35:27 -0500 Received: from g1t0038.austin.hp.com (g1t0038.austin.hp.com [16.236.32.44]) by g1t0027.austin.hp.com (Postfix) with ESMTP id B2C8E38017 for ; Tue, 26 Feb 2013 14:35:26 +0000 (UTC) Received: from ldl (ldl.usa.hp.com [16.125.112.222]) by g1t0038.austin.hp.com (Postfix) with ESMTP id A34743004B; Tue, 26 Feb 2013 14:35:26 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl (Postfix) with ESMTP id 454321A7E0E8; Tue, 26 Feb 2013 07:36:21 -0700 (MST) Received: from ldl ([127.0.0.1]) by localhost (ldl.fc.hp.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id mFK2GvguUely; Tue, 26 Feb 2013 07:36:21 -0700 (MST) Received: by ldl (Postfix, from userid 10474) id 201FC1A7E0EA; Tue, 26 Feb 2013 07:36:21 -0700 (MST) From: "Lee A. Roberts" To: netdev@vger.kernel.org Cc: lee.roberts@hp.com Subject: [PATCH 1/4] sctp: fix association hangs due to off-by-one errors in sctp_tsnmap_grow() Date: Tue, 26 Feb 2013 07:36:13 -0700 Message-Id: <1361889376-22171-2-git-send-email-lee.roberts@hp.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1361889376-22171-1-git-send-email-lee.roberts@hp.com> References: <1361889376-22171-1-git-send-email-lee.roberts@hp.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: "Lee A. Roberts" Resolve SCTP association hangs observed during SCTP stress testing. Observable symptoms include communications hangs with data being held in the association lobby (ordering) queue. Close examination of reassembly/ordering queues shows duplicated packets. In sctp_tsnmap_mark(), correct off-by-one error when calculating size value for sctp_tsnmap_grow(). In sctp_tsnmap_grow(), correct off-by-one error when copying and resizing the tsnmap. If max_tsn_seen is in the LSB of the word, this bit can be lost, causing the corresponding packet to be transmitted again and to be entered as a duplicate into the SCTP reassembly/ordering queues. Change parameter name from "gap" (zero-based index) to "size" (one-based) to enhance code readability. Signed-off-by: Lee A. Roberts Acked-by: Vlad Yasevich --- net/sctp/tsnmap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index 5f25e0c..396c451 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c @@ -51,7 +51,7 @@ static void sctp_tsnmap_update(struct sctp_tsnmap *map); static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off, __u16 len, __u16 *start, __u16 *end); -static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap); +static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size); /* Initialize a block of memory as a tsnmap. */ struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len, @@ -124,7 +124,7 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn, gap = tsn - map->base_tsn; - if (gap >= map->len && !sctp_tsnmap_grow(map, gap)) + if (gap >= map->len && !sctp_tsnmap_grow(map, gap + 1)) return -ENOMEM; if (!sctp_tsnmap_has_gap(map) && gap == 0) { @@ -360,23 +360,24 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map, return ngaps; } -static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap) +static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size) { unsigned long *new; unsigned long inc; u16 len; - if (gap >= SCTP_TSN_MAP_SIZE) + if (size > SCTP_TSN_MAP_SIZE) return 0; - inc = ALIGN((gap - map->len),BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT; + inc = ALIGN((size - map->len), BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT; len = min_t(u16, map->len + inc, SCTP_TSN_MAP_SIZE); new = kzalloc(len>>3, GFP_ATOMIC); if (!new) return 0; - bitmap_copy(new, map->tsn_map, map->max_tsn_seen - map->base_tsn); + bitmap_copy(new, map->tsn_map, + map->max_tsn_seen - map->cumulative_tsn_ack_point); kfree(map->tsn_map); map->tsn_map = new; map->len = len;