76bd0c0a9d
ppp based on these patches for about 3 weeks with no downtime. The original submitters comments: Two features iijppp has over kernel ppp that I like are predictor1 compression and demand dialing. Here are a few bug fixes. I expanded the priority queueing scheme and discovered it was broken due to the assignment at ip.c line 300. All packets were being queued at the same priority. Fixing priority queueing broke predictor1 compression. Packets were compressed before being queued and predictor1 worked as long as the packets were popped off the queue in the same order they were pushed onto the queue. There were a few byte order problems in IP header tests also. There is a recursion problem in SendLqrReport(). LcpClose() is called when "Too many echo packets are lost" which winds up in SendLqrReport() again. I believe the original intention was to just stop the LQR timer with the call to StopLqr() but the side effects hurt. Submitted by: John Capo <jc@irbs.com>
226 lines
5.2 KiB
C
226 lines
5.2 KiB
C
#include "fsm.h"
|
|
#include "hdlc.h"
|
|
#include "lcpproto.h"
|
|
#include "ccp.h"
|
|
|
|
/*
|
|
*
|
|
* $Id: pred.c,v 1.4 1996/01/10 21:27:59 phk Exp $
|
|
*
|
|
* pred.c -- Test program for Dave Rand's rendition of the
|
|
* predictor algorithm
|
|
* Updated by: iand@labtam.labtam.oz.au (Ian Donaldson)
|
|
* Updated by: Carsten Bormann <cabo@cs.tu-berlin.de>
|
|
* Original : Dave Rand <dlr@bungi.com>/<dave_rand@novell.com>
|
|
*/
|
|
|
|
/* The following hash code is the heart of the algorithm:
|
|
* It builds a sliding hash sum of the previous 3-and-a-bit characters
|
|
* which will be used to index the guess table.
|
|
* A better hash function would result in additional compression,
|
|
* at the expense of time.
|
|
*/
|
|
#define IHASH(x) iHash = (iHash << 4) ^ (x)
|
|
#define OHASH(x) oHash = (oHash << 4) ^ (x)
|
|
|
|
static unsigned short int iHash, oHash;
|
|
static unsigned char InputGuessTable[65536];
|
|
static unsigned char OutputGuessTable[65536];
|
|
|
|
static int
|
|
compress(source, dest, len)
|
|
unsigned char *source, *dest;
|
|
int len;
|
|
{
|
|
int i, bitmask;
|
|
unsigned char *flagdest, flags, *orgdest;
|
|
|
|
orgdest = dest;
|
|
while (len) {
|
|
flagdest = dest++; flags = 0; /* All guess wrong initially */
|
|
for (bitmask=1, i=0; i < 8 && len; i++, bitmask <<= 1) {
|
|
if (OutputGuessTable[oHash] == *source) {
|
|
flags |= bitmask; /* Guess was right - don't output */
|
|
} else {
|
|
OutputGuessTable[oHash] = *source;
|
|
*dest++ = *source; /* Guess wrong, output char */
|
|
}
|
|
OHASH(*source++);len--;
|
|
}
|
|
*flagdest = flags;
|
|
}
|
|
return(dest - orgdest);
|
|
}
|
|
|
|
static void
|
|
SyncTable(source, dest, len)
|
|
unsigned char *source, *dest;
|
|
int len;
|
|
{
|
|
|
|
while (len--) {
|
|
if (InputGuessTable[iHash] != *source) {
|
|
InputGuessTable[iHash] = *source;
|
|
}
|
|
IHASH(*dest++ = *source++);
|
|
}
|
|
}
|
|
|
|
static int
|
|
decompress(source, dest, len)
|
|
unsigned char *source, *dest;
|
|
int len;
|
|
{
|
|
int i, bitmask;
|
|
unsigned char flags, *orgdest;
|
|
|
|
orgdest = dest;
|
|
while (len) {
|
|
flags = *source++;
|
|
len--;
|
|
for (i=0, bitmask = 1; i < 8; i++, bitmask <<= 1) {
|
|
if (flags & bitmask) {
|
|
*dest = InputGuessTable[iHash]; /* Guess correct */
|
|
} else {
|
|
if (!len)
|
|
break; /* we seem to be really done -- cabo */
|
|
InputGuessTable[iHash] = *source; /* Guess wrong */
|
|
*dest = *source++; /* Read from source */
|
|
len--;
|
|
}
|
|
IHASH(*dest++);
|
|
}
|
|
}
|
|
return(dest - orgdest);
|
|
}
|
|
|
|
#define SIZ1 2048
|
|
|
|
void
|
|
Pred1Init(direction)
|
|
int direction;
|
|
{
|
|
if (direction & 1) { /* Input part */
|
|
iHash = 0;
|
|
bzero(InputGuessTable, sizeof(InputGuessTable));
|
|
}
|
|
if (direction & 2) { /* Output part */
|
|
oHash = 0;
|
|
bzero(OutputGuessTable, sizeof(OutputGuessTable));
|
|
}
|
|
}
|
|
|
|
void
|
|
Pred1Output(pri, proto, bp)
|
|
int pri;
|
|
u_short proto;
|
|
struct mbuf *bp;
|
|
{
|
|
struct mbuf *mwp;
|
|
u_char *cp, *wp, *hp;
|
|
int orglen, len;
|
|
u_char bufp[SIZ1];
|
|
u_short fcs;
|
|
|
|
orglen = plength(bp) + 2; /* add count of proto */
|
|
mwp = mballoc((orglen+2)/8*9+12, MB_HDLCOUT);
|
|
hp = wp = MBUF_CTOP(mwp);
|
|
cp = bufp;
|
|
*wp++ = *cp++ = orglen >> 8;
|
|
*wp++ = *cp++ = orglen & 0377;
|
|
*cp++ = proto >> 8;
|
|
*cp++ = proto & 0377;
|
|
mbread(bp, cp, orglen-2);
|
|
fcs = HdlcFcs(INITFCS, bufp, 2+orglen);
|
|
fcs = ~fcs;
|
|
|
|
len = compress(bufp + 2, wp, orglen);
|
|
#ifdef DEBUG
|
|
logprintf("orglen (%d) --> len (%d)\n", orglen, len);
|
|
#endif
|
|
CcpInfo.orgout += orglen;
|
|
if (len < orglen) {
|
|
*hp |= 0x80;
|
|
wp += len;
|
|
CcpInfo.compout += len;
|
|
} else {
|
|
bcopy(bufp+2, wp, orglen);
|
|
wp += orglen;
|
|
CcpInfo.compout += orglen;
|
|
}
|
|
|
|
*wp++ = fcs & 0377;
|
|
*wp++ = fcs >> 8;
|
|
mwp->cnt = wp - MBUF_CTOP(mwp);
|
|
HdlcOutput(PRI_NORMAL, PROTO_COMPD, mwp);
|
|
}
|
|
|
|
void
|
|
Pred1Input(bp)
|
|
struct mbuf *bp;
|
|
{
|
|
u_char *cp, *pp;
|
|
int len, olen, len1;
|
|
struct mbuf *wp;
|
|
u_char *bufp;
|
|
u_short fcs, proto;
|
|
|
|
wp = mballoc(SIZ1, MB_IPIN);
|
|
cp = MBUF_CTOP(bp);
|
|
olen = plength(bp);
|
|
pp = bufp = MBUF_CTOP(wp);
|
|
*pp++ = *cp & 0177;
|
|
len = *cp++ << 8;
|
|
*pp++ = *cp;
|
|
len += *cp++;
|
|
CcpInfo.orgin += len & 0x7fff;
|
|
if (len & 0x8000) {
|
|
len1 = decompress(cp, pp, olen - 4);
|
|
CcpInfo.compin += olen;
|
|
len &= 0x7fff;
|
|
if (len != len1) { /* Error is detected. Send reset request */
|
|
LogPrintf(LOG_LCP, "%s: Length Error\n", CcpFsm.name);
|
|
CcpSendResetReq(&CcpFsm);
|
|
pfree(bp);
|
|
pfree(wp);
|
|
return;
|
|
}
|
|
cp += olen - 4;
|
|
pp += len1;
|
|
} else {
|
|
CcpInfo.compin += len;
|
|
SyncTable(cp, pp, len);
|
|
cp += len;
|
|
pp += len;
|
|
}
|
|
*pp++ = *cp++; /* CRC */
|
|
*pp++ = *cp++;
|
|
fcs = HdlcFcs(INITFCS, bufp, wp->cnt = pp - bufp);
|
|
#ifdef DEBUG
|
|
if (fcs != GOODFCS)
|
|
logprintf("fcs = 0x%04x (%s), len = 0x%x, olen = 0x%x\n",
|
|
fcs, (fcs == GOODFCS)? "good" : "bad", len, olen);
|
|
#endif
|
|
if (fcs == GOODFCS) {
|
|
wp->offset += 2; /* skip length */
|
|
wp->cnt -= 4; /* skip length & CRC */
|
|
pp = MBUF_CTOP(wp);
|
|
proto = *pp++;
|
|
if (proto & 1) {
|
|
wp->offset++;
|
|
wp->cnt--;
|
|
} else {
|
|
wp->offset += 2;
|
|
wp->cnt -= 2;
|
|
proto = (proto << 8) | *pp++;
|
|
}
|
|
DecodePacket(proto, wp);
|
|
}
|
|
else
|
|
{
|
|
LogDumpBp(LOG_HDLC, "Bad FCS", wp);
|
|
pfree(wp);
|
|
}
|
|
pfree(bp);
|
|
}
|