[comp.sys.next] The joys of kernel hacking with no sources

louie@sayshell.umd.edu (Louis A. Mamakos) (06/19/91)

Well.

I finally discovered why my SLIP driver with VJ TCP header compression
wasn't working worth a damn.  Oh, and before anyone asks, the CSLIP driver
is not available for distribution quite yet.

It turns out that the TCP in the NeXT kernel (which feels close to a
4.3 Tahoe - 4.3 Reno; can't tell for sure since I only have a RENO and
the much different post-RENO development source code available to look
at).  This version of TCP will not send a TCP maxmimum segment size
option for computed MSS of less than 536 bytes.  This causes the SLIP
router that I was using to generate IP fragments since the MTU of the
compressed SLIP link is 256 bytes.  You lose big time!  Not only do
you not get a compressed TCP header, but now you get two IP headers
for every 536 bytes of data rather than just one!

Comparing the code fragment below from a 4.3 RENO tcp_output.c against the
disassembled /sdmach (courtesy 'otool -tvV /sdmach') shows a pretty good
match, and you can see cuperit:

04032338        btst    #1,d5			# TH_SYN
0403233c        beqs    0x4032392
0403233e        btst    #3,a4@(0x1b:w)		# TF_NOOPT
04032344        bnes    0x4032392
04032346        movel   a6@(0xfffc:w),a1	# first part of min macro
0403234a        movew   a1@(0x24:w),d0		# so->so_rcv.sb_hiwat
0403234e        lsrw    #1,d0			# ... / 2
04032350        clrl    a6@(0xffe8:w)		
04032354        movew   d0,a6@(0xffea:w)	# u_short mss
04032358        movel   a4,sp@-			# push tp
0403235a        bsrl    _tcp_mss
04032360        addqw   #0x4,sp			# pop stack
04032362        cmpl    a6@(0xffe8:w),d0	# compare
04032366        bles    0x4032374
04032368        movel   a6@(0xfffc:w),a1	# second part of min macro
0403236c        movew   a1@(0x24:w),d0		# so->so_rcv.sb_hiwat
04032370        lsrw    #1,d0			# ... / 2
04032372        bras    0x403237e
04032374        movel   a4,sp@-
04032376        bsrl    _tcp_mss
0403237c        addqw   #0x4,sp
0403237e        cmpw    #0x218,d0     # *** if (mss > IP_MSS - sizeof(...)) ****
04032382        blss    0x4032392
04032384        lea     _tcp_initopt,a3		# opt = tcp_initopt
0403238a        moveq   #4,d6			# optlen=4 (sizeof tcp_initopt)
0403238c        movew   d0,0x408fbe5:l		# splat
04032392        tstl    a3			# if (opt) ...
04032394        beqw    0x403241e

with

        /*
         * Before ESTABLISHED, force sending of initial options
         * unless TCP set to not do any options.
         */
        opt = NULL;
        if (flags & TH_SYN && (tp->t_flags & TF_NOOPT) == 0) {
                u_short mss;

                mss = min(so->so_rcv.sb_hiwat / 2, tcp_mss(tp));
                if (mss > IP_MSS - sizeof(struct tcpiphdr)) {
                        opt = tcp_initopt;
                        optlen = sizeof (tcp_initopt);
                        *(u_short *)(opt + 2) = htons(mss);
                }
        }
        if (opt) {

shows what the problem is.  The 'if (mss > IP_MSS - sizeof(struct
tcpiphdr))' test is going to screw you for compressed SLIP.

So, the question of the hour is: Is there a sanctioned way to patch
the mach kernel?  If this was a Sun or DECstation, I'd just rebuild
the kernel with a patched object file or even one that I'd recompile
from the BSD sources.  I have not yet tried to overwrite the kernel's
text segment from the SLIP loadable device driver; I don't know how
the memory protection is set up, if any.

I wrote a stupid program that opens /dev/kmem, and converts the
indicated instruction into a 'cmpw #0,d0'.  And now it sends the MSS
option on the TCP SYN segment and compresses SLIP works just fine.
This is an admittably ugly solution that I'm not real proud of.  But I
can't use adb either...

I wonder how Marble got around this problem?  Compressed SLIP without a
correct MSS option is a bit painful for > 250 bytes of data per packet,
and probably isn't worth trying to use.

Good thing this isn't a RISC processor; it'd be more difficult to read
the disassembled code!

louie