From patchwork Fri Oct 9 16:16:10 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Krzysztof Halasa X-Patchwork-Id: 35634 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.176.167]) by ozlabs.org (Postfix) with ESMTP id DA00AB7B69 for ; Sat, 10 Oct 2009 03:19:55 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933789AbZJIQQu (ORCPT ); Fri, 9 Oct 2009 12:16:50 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S933751AbZJIQQu (ORCPT ); Fri, 9 Oct 2009 12:16:50 -0400 Received: from khc.piap.pl ([195.187.100.11]:42092 "EHLO khc.piap.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760909AbZJIQQt convert rfc822-to-8bit (ORCPT ); Fri, 9 Oct 2009 12:16:49 -0400 Received: from intrepid.localdomain (intrepid.localdomain [10.0.0.2]) by khc.piap.pl (Postfix) with ESMTP id 9FA81931F; Fri, 9 Oct 2009 18:16:10 +0200 (CEST) From: Krzysztof Halasa To: David Miller Cc: Subject: [PATCH] WAN: fix Cisco HDLC handshaking. Date: Fri, 09 Oct 2009 18:16:10 +0200 Message-ID: MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org WAN: fix Cisco HDLC handshaking. Cisco HDLC uses keepalive packets and sequence numbers to determine link state. In rare cases both ends could transmit keepalive packets at the same time, causing the received sequence numbers to be treated as incorrect. Now we accept our current sequence number as well as the previous one. Signed-off-by: Krzysztof HaƂasa diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index cf5fd17..f1bff98 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -58,8 +58,7 @@ struct cisco_state { spinlock_t lock; unsigned long last_poll; int up; - int request_sent; - u32 txseq; /* TX sequence number */ + u32 txseq; /* TX sequence number, 0 = none */ u32 rxseq; /* RX sequence number */ }; @@ -163,6 +162,7 @@ static int cisco_rx(struct sk_buff *skb) struct cisco_packet *cisco_data; struct in_device *in_dev; __be32 addr, mask; + u32 ack; if (skb->len < sizeof(struct hdlc_header)) goto rx_error; @@ -223,8 +223,10 @@ static int cisco_rx(struct sk_buff *skb) case CISCO_KEEPALIVE_REQ: spin_lock(&st->lock); st->rxseq = ntohl(cisco_data->par1); - if (st->request_sent && - ntohl(cisco_data->par2) == st->txseq) { + ack = ntohl(cisco_data->par2); + if (ack && (ack == st->txseq || + /* our current REQ may be in transit */ + ack == st->txseq - 1)) { st->last_poll = jiffies; if (!st->up) { u32 sec, min, hrs, days; @@ -275,7 +277,6 @@ static void cisco_timer(unsigned long arg) cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, htonl(++st->txseq), htonl(st->rxseq)); - st->request_sent = 1; spin_unlock(&st->lock); st->timer.expires = jiffies + st->settings.interval * HZ; @@ -293,9 +294,7 @@ static void cisco_start(struct net_device *dev) unsigned long flags; spin_lock_irqsave(&st->lock, flags); - st->up = 0; - st->request_sent = 0; - st->txseq = st->rxseq = 0; + st->up = st->txseq = st->rxseq = 0; spin_unlock_irqrestore(&st->lock, flags); init_timer(&st->timer); @@ -317,8 +316,7 @@ static void cisco_stop(struct net_device *dev) spin_lock_irqsave(&st->lock, flags); netif_dormant_on(dev); - st->up = 0; - st->request_sent = 0; + st->up = st->txseq = 0; spin_unlock_irqrestore(&st->lock, flags); }