Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Jun 1997 08:30:01 -0700 (PDT)
From:      Peter Wemm <peter@spinner.dialix.com.au>
To:        freebsd-bugs
Subject:   Re: kern/3925: SO_SNDLOWAT of 0 causes kernel to use 99% of CPU time on TCP send 
Message-ID:  <199706221530.IAA06836@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/3925; it has been noted by GNATS.

From: Peter Wemm <peter@spinner.dialix.com.au>
To: sthaug@nethelp.no
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: kern/3925: SO_SNDLOWAT of 0 causes kernel to use 99% of CPU time on TCP send 
Date: Sun, 22 Jun 1997 23:20:44 +0800

 When setting the parameters, there is no validity checking:
                         case SO_SNDBUF:
                         case SO_RCVBUF:
                                 if (sbreserve(optname == SO_SNDBUF ?   
                                     &so->so_snd : &so->so_rcv,
                                     (u_long) *mtod(m, int *)) == 0) {
                                         error = ENOBUFS;
                                         goto bad;
                                 }
                                 break;
 
                         case SO_SNDLOWAT:
                                 so->so_snd.sb_lowat = *mtod(m, int *);
                                 break;
                         case SO_RCVLOWAT:
                                 so->so_rcv.sb_lowat = *mtod(m, int *);
                                 break;
                         }
 
 However, soreserve() clips the results:
 soreserve(so, sndcc, rcvcc)
 {
         if (sbreserve(&so->so_snd, sndcc) == 0)
                 goto bad;
         if (sbreserve(&so->so_rcv, rcvcc) == 0)
                 goto bad2;
         if (so->so_rcv.sb_lowat == 0)
                 so->so_rcv.sb_lowat = 1;
         if (so->so_snd.sb_lowat == 0)
                 so->so_snd.sb_lowat = MCLBYTES;
         if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
                 so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
         return (0);
 [..]
 
 sbreserve() also clips:
 
 sbreserve(sb, cc)
 {
 [..]
         sb->sb_hiwat = cc;
         sb->sb_mbmax = min(cc * sb_efficiency, sb_max);
         if (sb->sb_lowat > sb->sb_hiwat)
                 sb->sb_lowat = sb->sb_hiwat;
         return (1);
 [..]
 
 It seems to me that SO_SNDLOWAT = 0 is an error..  Depending on the timing 
 of the setsockopt() calls relative to when soreserve() has been called, a 
 value of zero is set to MCLBYTES or left at zero.
 
 I suspect the reason that there is no parameter checking at set time is so 
 that the sanity checking is done after _all_ the parameters are set..  
 Otherwise, doing a series of setsockopt()'s could be a bit hairy if all 
 combinations along the way were sanity checked.  For example, if lowat is 
 1 and hiwat is 1024, and you wanted to change it to 2048/8192, under the 
 present system setting lowat to 2048 first then hiwat next would work, but 
 checking lowat > hiwat along the way would leave you with 1/8192 as a 
 result which is not what would be expected.
 
 I guess the question is, when is soreserve() called to do the sanity 
 check?  Does this mean that soreserve() is being missed somewhere along 
 the way and allowing nonsensical hi/low values to be used on a different 
 size buffer?
 
 Cheers,
 -Peter
 
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199706221530.IAA06836>