home *** CD-ROM | disk | FTP | other *** search
- *** cslip.c Fri Nov 6 03:54:11 1992
- --- cslip.c.new Fri Nov 6 17:07:20 1992
- ***************
- *** 10,15 ****
- --- 10,19 ----
- * time and always left open. To do slattach, a module is pushed
- * on a tty device and an ioctl done on it to find out which slip
- * interface should be started up using ifconfig(1).
- + *
- + * 92-11-6:
- + * V1.1 Markus Wild integrated TCP header compression and added code
- + * to favor interactive traffic over regular traffic
- */
-
- #include "sys/types.h"
- ***************
- *** 34,46 ****
- --- 38,72 ----
- #include "netinet/in.h"
- #include "netinet/in_var.h"
- #include "netinet/ip_str.h"
- + #include "netinet/in_systm.h"
- + #include "netinet/ip.h"
- + #include "netinet/tcp.h"
-
- extern struct ifstats *ifstats; /* per-interface statistics for inet */
-
- + #include "slcompress.h"
- #include "slip.h"
-
- + /* the code to deal with interactive traffic is from the cslip reference
- + code, sunos/ directory (for streams) */
- +
- + /*
- + * The following hack gets around the problem that IP TOS
- + * can't be set in BSD/Sun OS yet. We want to put "interactive"
- + * traffic on a high priority queue. To decide if traffic is
- + * interactive, we check that a) it is TCP and b) one of it's ports
- + * if telnet, rlogin or ftp control.
- + */
- + static u_short interactive_ports[8] = {
- + 0, 513, 0, 0,
- + 0, 21, 0, 23,
- + };
- + #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
- +
-
- #define SLIP_WHICH_INTERFACE 'slwh'
- + #define SLIP_GET_CONF_FLAGS 'slgc'
- + #define SLIP_SET_CONF_FLAGS 'slsc'
-
- #define SLIP_DLPI_MID 'SD' /* DLPI Module ID */
- #define SLIP_TTY_MID 'ST' /* TTY Module ID */
- ***************
- *** 47,56 ****
- --- 73,145 ----
-
- #define SLIP_MAXDEV 5 /* Maximum number of simultaneous */
- /* active SLIP interfaces. */
- +
- + /* explanatory text to the BSD code. I used the suggested MTU, but am
- + * for now using a much higher hi/lo-water pair (seems streams-specific) */
- +
- + /*
- + * SLMAX is a hard limit on input packet size. To simplify the code
- + * and improve performance, we require that packets fit in an mbuf
- + * cluster, and if we get a compressed packet, there's enough extra
- + * room to expand the header into a max length tcp/ip header (128
- + * bytes). So, SLMAX can be at most
- + * MCLBYTES - 128
- + *
- + * SLMTU is a hard limit on output packet size. To insure good
- + * interactive response, SLMTU wants to be the smallest size that
- + * amortizes the header cost. (Remember that even with
- + * type-of-service queuing, we have to wait for any in-progress
- + * packet to finish. I.e., we wait, on the average, 1/2 * mtu /
- + * cps, where cps is the line speed in characters per second.
- + * E.g., 533ms wait for a 1024 byte MTU on a 9600 baud line. The
- + * average compressed header size is 6-8 bytes so any MTU > 90
- + * bytes will give us 90% of the line bandwidth. A 100ms wait is
- + * tolerable (500ms is not), so want an MTU around 296. (Since TCP
- + * will send 256 byte segments (to allow for 40 byte headers), the
- + * typical packet size on the wire will be around 260 bytes). In
- + * 4.3tahoe+ systems, we can set an MTU in a route so we do that &
- + * leave the interface MTU relatively high (so we don't IP fragment
- + * when acting as a gateway to someone using a stupid MTU).
- + *
- + * Similar considerations apply to SLIP_HIWAT: It's the amount of
- + * data that will be queued 'downstream' of us (i.e., in clists
- + * waiting to be picked up by the tty output interrupt). If we
- + * queue a lot of data downstream, it's immune to our t.o.s. queuing.
- + * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed
- + * telnet/ftp will see a 1 sec wait, independent of the mtu (the
- + * wait is dependent on the ftp window size but that's typically
- + * 1k - 4k). So, we want SLIP_HIWAT just big enough to amortize
- + * the cost (in idle time on the wire) of the tty driver running
- + * off the end of its clists & having to call back slstart for a
- + * new packet. For a tty interface with any buffering at all, this
- + * cost will be zero. Even with a totally brain dead interface (like
- + * the one on a typical workstation), the cost will be <= 1 character
- + * time. So, setting SLIP_HIWAT to ~100 guarantees that we'll lose
- + * at most 1% while maintaining good interactive response.
- + */
- + #if 0 /* BSD implementation constants described in above text */
- + #define BUFOFFSET 128
- + #define SLMAX (MCLBYTES - BUFOFFSET)
- + #define SLBUFSIZE (SLMAX + BUFOFFSET)
- + #define SLMTU 296
- + #define SLIP_HIWAT roundup(50,CBSIZE)
- + #define CLISTRESERVE 1024 /* Can't let clists get too low */
- + #else
- + #ifdef COMMODORE_PARAMETERS
- #define SLIP_MIN 1
- #define SLIP_MAX 1006 /* Is this some sort of standard? */
- + #define SLIP_MTU SLIP_MAX
- #define SLIP_HIWAT 2048
- #define SLIP_LOWAT (2*SLIP_HIWAT/3)
- + #else
- + #define SLIP_MIN 1
- + #define SLIP_MAX 1006 /* Is this some sort of standard? */
- + #define SLIP_MTU 296
- + #define SLIP_HIWAT 100
- + #define SLIP_LOWAT (2*SLIP_HIWAT/3)
- + #endif
- + #define BUFOFFSET 128 /* room for decompressed header */
- + #endif
-
- struct slipdev
- {
- ***************
- *** 62,69 ****
- --- 151,167 ----
- char ifname[20];
- mblk_t *curblk; /* Input packet being assembled */
- int escaped; /* Last character was ESCAPE */
- +
- + u_int sc_flags; /* see below */
- + struct slcompress sc_comp; /* tcp compression data */
- + mblk_t *lastpriopkt; /* last priority interactive message */
- };
-
- + /* visible flags */
- + #define SC_COMPRESS 0x0002 /* compress TCP traffic */
- + #define SC_NOICMP 0x0004 /* supress ICMP traffic */
- + #define SC_AUTOCOMP 0x0008 /* auto-enable TCP compression */
- +
-
- /*
- * DLPI stream data structure definitions
- ***************
- *** 75,81 ****
- --- 173,184 ----
-
- static struct module_info dlpi_minfo =
- {
- + #ifdef COMMODORE_PARAMETERS
- SLIP_DLPI_MID, "sld", SLIP_MIN, SLIP_MAX, SLIP_HIWAT, SLIP_LOWAT,
- + #else
- + /* these parameters are from the SunOS streams code, who is right?? */
- + SLIP_DLPI_MID, "sld", 0, INFPSZ, 16384, 4096,
- + #endif
- };
-
- static struct qinit dlpirinit =
- ***************
- *** 101,107 ****
- --- 204,214 ----
-
- static struct module_info tty_minfo =
- {
- + #ifdef COMMODORE_PARAMETERS
- SLIP_TTY_MID, "slipmod", SLIP_MIN, SLIP_MAX, SLIP_HIWAT, SLIP_LOWAT,
- + #else
- + SLIP_TTY_MID, "slipmod", 0, INFPSZ, 16384, 4096,
- + #endif
- };
-
- static struct qinit ttyrinit =
- ***************
- *** 164,170 ****
- }
-
- slip->stats.ifs_active = 1;
- ! slip->stats.ifs_mtu = SLIP_MAX;
- slip->stats.ifs_ipackets =
- slip->stats.ifs_ierrors =
- slip->stats.ifs_opackets =
- --- 271,277 ----
- }
-
- slip->stats.ifs_active = 1;
- ! slip->stats.ifs_mtu = SLIP_MTU;
- slip->stats.ifs_ipackets =
- slip->stats.ifs_ierrors =
- slip->stats.ifs_opackets =
- ***************
- *** 172,177 ****
- --- 279,289 ----
-
- WR(rq)->q_ptr = rq->q_ptr = (caddr_t)slip;
- slip->dlpiq = rq;
- +
- + /* seems like a reasonable default to me */
- + slip->sc_flags = SC_AUTOCOMP;
- + sl_compress_init (& slip->sc_comp);
- + slip->lastpriopkt = 0;
- }
-
- return 0;
- ***************
- *** 448,454 ****
- register struct slipdev *slip;
- mblk_t *dlpimp;
- {
- ! mblk_t *bp, *outmp;
-
- if (!canput(WR(slip->ttyq)))
- return 0;
- --- 560,568 ----
- register struct slipdev *slip;
- mblk_t *dlpimp;
- {
- ! mblk_t *bp, *outmp, *tmpmp=0;
- ! struct ip *ip;
- ! int s, p, hiprio;
-
- if (!canput(WR(slip->ttyq)))
- return 0;
- ***************
- *** 461,469 ****
- }
- outmp->b_datap->db_type = M_DATA;
-
- #define putc(ch) (*outmp->b_wptr++ = (ch))
- /* Copy input to output, escaping special characters */
- ! for ( bp=dlpimp->b_cont ; bp ; bp=bp->b_cont )
- while (bp->b_wptr > bp->b_rptr)
- {
- unsigned char c = *bp->b_rptr++;
- --- 575,624 ----
- }
- outmp->b_datap->db_type = M_DATA;
-
- + ip = (struct ip *)(dlpimp->b_cont->b_rptr);
- + hiprio = 0;
- + if (ip->ip_p == IPPROTO_TCP)
- + {
- + if (slip->sc_flags & SC_COMPRESS)
- + {
- + /* copy over the chain of mblk_t into one buffer. This is to
- + make sure the compression code can assume the whole mess
- + is one packet. It probably would do to just convert the
- + first buffer, but since I don't have any documentation to
- + mblk_t internals.. */
- + if (!(tmpmp = allocb (SLIP_MAX, BPRI_MED)))
- + {
- + ++slip->stats.ifs_oerrors;
- + freemsg (outmp);
- + return 0;
- + }
- + for (bp = dlpimp->b_cont; bp; bp = bp->b_cont)
- + while (bp->b_wptr > bp->b_rptr)
- + *tmpmp->b_wptr++ = *bp->b_rptr++;
- +
- + /* ok, compress the sucker */
- + ip = (struct ip *) tmpmp->b_rptr;
- + p = ((int *)ip)[ip->ip_hl];
- + hiprio = INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16);
- + p = sl_compress_tcp (tmpmp, ip, &slip->sc_comp, hiprio);
- + *(u_char *) tmpmp->b_rptr |= p; /* what the ... */
- + bp = tmpmp;
- + }
- + else if ((slip->sc_flags & SC_NOICMP) && ip->ip_p == IPPROTO_ICMP)
- + {
- + freemsg (tmpmp);
- + freemsg (outmp);
- + return 0;
- + }
- + else
- + bp = dlpimp->b_cont;
- + }
- + else
- + bp = dlpimp->b_cont;
- +
- #define putc(ch) (*outmp->b_wptr++ = (ch))
- /* Copy input to output, escaping special characters */
- ! for ( ; bp ; bp=bp->b_cont )
- while (bp->b_wptr > bp->b_rptr)
- {
- unsigned char c = *bp->b_rptr++;
- ***************
- *** 489,497 ****
- #undef putc
-
- ++slip->stats.ifs_opackets;
- putnext(WR(slip->ttyq), outmp);
- ! freemsg(dlpimp);
-
- return 1;
- }
-
- --- 644,694 ----
- #undef putc
-
- ++slip->stats.ifs_opackets;
- + #if 1
- + /* then queue it for later transmission through the port */
- + s = splstr();
- + if (WR(slip->ttyq))
- + { /* inside splstr() in case WR(slip->ttyq) = 0 */
- + if (hiprio)
- + { /* macchiavelli mode */
- + register mblk_t *tp = WR(slip->ttyq)->q_next->q_first;
- + /*
- + * We want this packet to come before other
- + * IP packets but after other TELNET/LOGINSERVER
- + * packets, ignoring real priority messages.
- + */
- + for (; tp != NULL; tp = tp->b_next)
- + if (tp == slip->lastpriopkt)
- + break;
- + if (tp == NULL)
- + tp = WR(slip->ttyq)->q_next->q_first;
- + if (tp == NULL)
- + /* since insq doesn't schedule the q! */
- + putnext(WR(slip->ttyq), outmp);
- + else
- + insq(WR(slip->ttyq)->q_next, tp, outmp);
- + slip->lastpriopkt = outmp;
- + }
- + else
- + putnext(WR(slip->ttyq), outmp);
- + }
- + else
- + {
- + freemsg(outmp);
- + outmp = 0;
- + }
- + (void) splx(s);
- + #else
- putnext(WR(slip->ttyq), outmp);
- ! #endif
- ! if (tmpmp)
- ! freemsg (tmpmp);
-
- + if (outmp)
- + freemsg(dlpimp);
- + else
- + return 0;
- +
- return 1;
- }
-
- ***************
- *** 634,639 ****
- --- 831,837 ----
- {
- register struct slipdev *slip = (struct slipdev *)q->q_ptr;
- struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
- + int s;
-
- switch (iocbp->ioc_cmd)
- {
- ***************
- *** 640,645 ****
- --- 838,868 ----
- case SLIP_WHICH_INTERFACE:
- RETURN(M_IOCACK, slip-sliptab, 0);
-
- + case SLIP_GET_CONF_FLAGS:
- + RETURN(M_IOCACK, slip->sc_flags, 0);
- +
- + case SLIP_SET_CONF_FLAGS:
- + if (iocbp->ioc_count == TRANSPARENT)
- + {
- + slip->sc_flags = (*(long *)mp->b_cont->b_rptr) & 0xffff;
- + /* printf("sl: setting flags 0x%x\n", slip->sc_flags);*/
- + freemsg (mp->b_cont);
- + mp->b_cont = 0;
- + RETURN(M_IOCACK, 0, 0);
- + }
- + else
- + {
- + /* fail if I_STR (from streams guide) */
- + if (mp->b_cont)
- + {
- + freemsg (mp->b_cont);
- + mp->b_cont = 0;
- + }
- + mp->b_datap->db_type = M_IOCNAK;
- + qreply (q, mp);
- + break;
- + }
- +
- default:
- RETURN(M_IOCNAK, 0, EINVAL);
- }
- ***************
- *** 681,702 ****
- {
- mblk_t *dlpimp;
- register dl_unitdata_ind_t *udp;
- dlpimp = allocb(sizeof *udp, BPRI_MED);
- if (dlpimp)
- ! {
- ! udp = (dl_unitdata_ind_t *)dlpimp->b_wptr;
- ! udp->dl_primitive = DL_UNITDATA_IND;
- ! udp->dl_dest_addr_length = 0;
- ! udp->dl_dest_addr_offset = sizeof *udp;
- ! udp->dl_src_addr_length = 0;
- ! udp->dl_src_addr_offset = sizeof *udp;
- ! udp->dl_reserved = 0;
- !
- ! dlpimp->b_wptr += sizeof *udp;
- ! dlpimp->b_datap->db_type = M_PROTO;
- ! dlpimp->b_cont = outmp;
- ! ++slip->stats.ifs_ipackets;
- ! putnext(slip->dlpiq, dlpimp);
- }
- else
- freemsg(outmp);
- --- 904,965 ----
- {
- mblk_t *dlpimp;
- register dl_unitdata_ind_t *udp;
- + int c;
- +
- dlpimp = allocb(sizeof *udp, BPRI_MED);
- if (dlpimp)
- ! {
- ! int ok = 1;
- !
- ! if ((c = (*outmp->b_rptr & 0xf0)) !=
- ! (IPVERSION << 4))
- ! {
- ! if (c & 0x80)
- ! c = TYPE_COMPRESSED_TCP;
- ! else if (c == TYPE_UNCOMPRESSED_TCP)
- ! *outmp->b_rptr &= 0x4f; /* XXX */
- ! /*
- ! * We've got something that's not an IP packet.
- ! * If compression is enabled, try to decompress it.
- ! * Otherwise, if `auto-enable' compression is on and
- ! * it's a reasonable packet, decompress it and then
- ! * enable compression. Otherwise, drop it.
- ! */
- ! if (slip->sc_flags & SC_COMPRESS)
- ! ok = sl_uncompress_tcp (outmp, (u_int)c,
- ! &slip->sc_comp);
- ! else if ((slip->sc_flags & SC_AUTOCOMP) &&
- ! c == TYPE_UNCOMPRESSED_TCP &&
- ! outmp->b_wptr - outmp->b_rptr >= 40)
- ! {
- ! ok = sl_uncompress_tcp (outmp, (u_int)c,
- ! &slip->sc_comp);
- ! if (ok > 0)
- ! slip->sc_flags |= SC_COMPRESS;
- ! }
- ! }
- !
- ! if (ok <= 0)
- ! {
- ! freemsg (outmp);
- ! freemsg (dlpimp);
- ! }
- ! else
- ! {
- ! udp = (dl_unitdata_ind_t *)dlpimp->b_wptr;
- ! udp->dl_primitive = DL_UNITDATA_IND;
- ! udp->dl_dest_addr_length = 0;
- ! udp->dl_dest_addr_offset = sizeof *udp;
- ! udp->dl_src_addr_length = 0;
- ! udp->dl_src_addr_offset = sizeof *udp;
- ! udp->dl_reserved = 0;
- !
- ! dlpimp->b_wptr += sizeof *udp;
- ! dlpimp->b_datap->db_type = M_PROTO;
- ! dlpimp->b_cont = outmp;
- ! ++slip->stats.ifs_ipackets;
- ! putnext(slip->dlpiq, dlpimp);
- ! }
- }
- else
- freemsg(outmp);
- ***************
- *** 727,734 ****
-
- /* if packet is too large, drop it and start over */
- if (!outmp)
- ! if (outmp=allocb(SLIP_MAX, BPRI_MED))
- slip->curblk = outmp;
- else
- {
- ++slip->stats.ifs_ierrors;
- --- 990,1003 ----
-
- /* if packet is too large, drop it and start over */
- if (!outmp)
- ! if (outmp=allocb(SLIP_MAX+BUFOFFSET, BPRI_MED))
- ! {
- slip->curblk = outmp;
- + /* make a hole to possibly insert a decompressed
- + header */
- + outmp->b_wptr = outmp->b_rptr =
- + outmp->b_datap->db_base + BUFOFFSET;
- + }
- else
- {
- ++slip->stats.ifs_ierrors;
- ***************
- *** 739,745 ****
- {
- ++slip->stats.ifs_ierrors;
- outmp->b_wptr = outmp->b_rptr =
- ! outmp->b_datap->db_base;
- }
-
- *outmp->b_wptr++ = c;
- --- 1008,1014 ----
- {
- ++slip->stats.ifs_ierrors;
- outmp->b_wptr = outmp->b_rptr =
- ! outmp->b_datap->db_base + BUFOFFSET;
- }
-
- *outmp->b_wptr++ = c;
-