*BSD News Article 14676


Return to BSD News archive

Newsgroups: comp.os.386bsd.bugs
Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!haven.umd.edu!uunet!mcsun!sun4nl!izfcs!tom
From: tom@izf.tno.nl (Tom Vijlbrief)
Subject: Fix for hanging slip
Message-ID: <C5pzBs.66J@izf.tno.nl>
Organization: TNO Institute for Perception
Date: Mon, 19 Apr 1993 07:26:16 GMT
Lines: 86

I experienced trouble with slip on both a 486 Notebook
and a Compaq 386sx deskpro. After sending a few megabytes
of data slip hangs, and netstat shows a rising oerr
count and ping reports 'no more buffer space'.

This is probably caused by a missed transmitter queue empty interrupt,
at which point the queue is just filled to its max length and all
packets are dropped.
(I experienced the same lost interrupt problem when debugging a serial line
driver routine for a Messy DOS slip router). This patch detects this situation
and restarts by a call to slstart.

Tom
===============================================================================
Tom Vijlbrief
TNO Institute for Perception		Phone: +31 34 63 562 11
P.O. Box 23				Fax:   +31 34 63 539 77
3769 ZG  Soesterberg			E-mail: tom@izf.tno.nl
The Netherlands
===============================================================================

*** org/if_slvar.h	Sun Apr 18 14:35:52 1993
--- if_slvar.h	Sun Apr 18 14:37:26 1993
***************
*** 62,67 ****
--- 62,69 ----
  	long	sc_lasttime;		/* last time a char arrived */
  	long	sc_starttime;		/* last time a char arrived */
  	long	sc_abortcount;		/* number of abort esacpe chars */
+ 	/* PATCH, tom@izf.tno.nl */
+ 	u_int	sc_prevqueue;		/* previous queue length (detects deadlock) */
  #ifdef INET				/* XXX */
  	struct	slcompress sc_comp;	/* tcp compression data */
  #endif
*** org/if_sl.c	Sun Apr 18 14:39:51 1993
--- if_sl.c	Sun Apr 18 14:42:00 1993
***************
*** 89,94 ****
--- 89,96 ----
  #include "kernel.h"
  #include "conf.h"
  
+ #include "syslog.h"
+ 
  #include "if.h"
  #include "if_types.h"
  #include "netisr.h"
***************
*** 388,393 ****
--- 390,405 ----
  		return (0);
  	}
  	s = splimp();
+ 
+ 	/* PATCH: Detect hanging output queue, tom@izf.tno.nl */
+ 	if (sc->sc_prevqueue
+ 	   && RB_LEN(&sc->sc_ttyp->t_out) == sc->sc_prevqueue
+ 	   && (((time.tv_sec - sc->sc_if.if_lastchange.tv_sec) * hz +
+ 	   (time.tv_usec - sc->sc_if.if_lastchange.tv_usec) * hz / 1000000) > 1)) {
+ 		log(LOG_NOTICE, "slip queue hangs, restarting\n");
+ 		slstart(sc->sc_ttyp);
+ 	}
+ 
  	if (IF_QFULL(ifq)) {
  		IF_DROP(ifq);
  		m_freem(m);
***************
*** 397,403 ****
  	}
  	IF_ENQUEUE(ifq, m);
  	sc->sc_if.if_lastchange = time;
! 	if (RB_LEN(&sc->sc_ttyp->t_out) == 0)
  		slstart(sc->sc_ttyp);
  	splx(s);
  	return (0);
--- 409,416 ----
  	}
  	IF_ENQUEUE(ifq, m);
  	sc->sc_if.if_lastchange = time;
! 	/* PATCH: tom@izf.tno.nl */
! 	if ((sc->sc_prevqueue= RB_LEN(&sc->sc_ttyp->t_out)) == 0)
  		slstart(sc->sc_ttyp);
  	splx(s);
  	return (0);