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