X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=modules%2Fbsd-comp.c;h=d30e0d25f69da08dc4781cdfc6e1b58e85f0e9c0;hp=f2a688c4805b1b17be51355d3df98c437f8713be;hb=adc8347e757be7d7ccd220fd09d22c48884e64bc;hpb=9e6f1c03381c15085f184a606abf81d7c514c9da diff --git a/modules/bsd-comp.c b/modules/bsd-comp.c index f2a688c..d30e0d2 100644 --- a/modules/bsd-comp.c +++ b/modules/bsd-comp.c @@ -38,18 +38,41 @@ */ /* - * This version is for use with STREAMS under SunOS 4.x. + * This version is for use with STREAMS under SunOS 4.x, + * DEC Alpha OSF/1, and AIX 4.x. * - * $Id: bsd-comp.c,v 1.4 1994/09/16 02:06:31 paulus Exp $ + * $Id: bsd-comp.c,v 1.8 1994/12/08 00:35:33 paulus Exp $ */ +#ifdef __aix4__ +#include +#endif #include #include #include -#include +#include +#include +#include #include -#define PACKET mblk_t +#ifdef sun +#include +#define ALLOCATE(n) kmem_alloc((n), KMEM_NOSLEEP) +#define FREE(p, n) kmem_free((p), (n)) +#endif + +#ifdef __osf__ +#include +#define ALLOCATE(n) kalloc((n)) +#define FREE(p, n) kfree((p), (n)) +#endif + +#ifdef __aix4__ +#define ALLOCATE(n) xmalloc((n), 0, pinned_heap) +#define FREE(p, n) xmfree((p), pinned_heap) +#endif + +#define PACKETPTR mblk_t * #include /* @@ -94,16 +117,22 @@ struct bsd_db { u_char maxbits; u_char debug; u_char unit; - u_short mru; u_short seqno; /* sequence number of next packet */ + u_int hdrlen; /* header length to preallocate */ + u_int mru; u_int maxmaxcode; /* largest valid code */ u_int max_ent; /* largest code in use */ - u_int in_count; /* uncompressed bytes */ - u_int bytes_out; /* compressed bytes */ + u_int in_count; /* uncompressed bytes, aged */ + u_int bytes_out; /* compressed bytes, aged */ u_int ratio; /* recent compression ratio */ - u_int checkpoint; /* when to next check the ratio */ - int clear_count; /* times dictionary cleared */ - int incomp_count; /* incompressible packets */ + u_int checkpoint; /* when to next check the ratio */ + u_int clear_count; /* times dictionary cleared */ + u_int incomp_count; /* incompressible packets */ + u_int incomp_bytes; /* incompressible bytes */ + u_int uncomp_count; /* uncompressed packets */ + u_int uncomp_bytes; /* uncompressed bytes */ + u_int comp_count; /* compressed packets */ + u_int comp_bytes; /* compressed bytes */ u_short *lens; /* array of lengths of codes */ struct bsd_dict { union { /* hash value */ @@ -136,12 +165,13 @@ static void bsd_free __P((void *state)); static int bsd_comp_init __P((void *state, u_char *options, int opt_len, int unit, int debug)); static int bsd_decomp_init __P((void *state, u_char *options, int opt_len, - int unit, int mru, int debug)); + int unit, int hdrlen, int mru, int debug)); static int bsd_compress __P((void *state, mblk_t **mret, mblk_t *mp, int slen, int maxolen)); static void bsd_incomp __P((void *state, mblk_t *dmsg)); static int bsd_decompress __P((void *state, mblk_t *cmp, mblk_t **dmpp)); static void bsd_reset __P((void *state)); +static void bsd_comp_stats __P((void *state, struct compstat *stats)); /* * Procedures exported to ppp_comp.c. @@ -153,12 +183,14 @@ struct compressor ppp_bsd_compress = { bsd_comp_init, /* comp_init */ bsd_reset, /* comp_reset */ bsd_compress, /* compress */ + bsd_comp_stats, /* comp_stat */ bsd_decomp_alloc, /* decomp_alloc */ bsd_free, /* decomp_free */ bsd_decomp_init, /* decomp_init */ bsd_reset, /* decomp_reset */ bsd_decompress, /* decompress */ bsd_incomp, /* incomp */ + bsd_comp_stats, /* decomp_stat */ }; /* @@ -253,6 +285,33 @@ bsd_check(db) return 0; } +/* + * Return statistics. + */ +static void +bsd_comp_stats(state, stats) + void *state; + struct compstat *stats; +{ + struct bsd_db *db = (struct bsd_db *) state; + u_int out; + + stats->unc_bytes = db->uncomp_bytes; + stats->unc_packets = db->uncomp_count; + stats->comp_bytes = db->comp_bytes; + stats->comp_packets = db->comp_count; + stats->inc_bytes = db->incomp_bytes; + stats->inc_packets = db->incomp_count; + stats->ratio = db->in_count; + out = db->bytes_out; + if (stats->ratio <= 0x7fffff) + stats->ratio <<= 8; + else + out >>= 8; + if (out != 0) + stats->ratio /= out; +} + /* * Reset state, as on a CCP ResetReq. */ @@ -313,7 +372,7 @@ bsd_alloc(options, opt_len, decomp) maxmaxcode = MAXCODE(bits); newlen = sizeof(*db) + (hsize-1) * (sizeof(db->dict[0])); - db = (struct bsd_db *) kmem_alloc(newlen, KMEM_NOSLEEP); + db = (struct bsd_db *) ALLOCATE(newlen); if (!db) return NULL; bzero(db, sizeof(*db) - sizeof(db->dict)); @@ -321,10 +380,9 @@ bsd_alloc(options, opt_len, decomp) if (!decomp) { db->lens = NULL; } else { - db->lens = (u_short *) kmem_alloc((maxmaxcode+1) * sizeof(db->lens[0]), - KMEM_NOSLEEP); + db->lens = (u_short *) ALLOCATE((maxmaxcode+1) * sizeof(db->lens[0])); if (!db->lens) { - kmem_free(db, newlen); + FREE(db, newlen); return NULL; } } @@ -345,8 +403,8 @@ bsd_free(state) struct bsd_db *db = (struct bsd_db *) state; if (db->lens) - kmem_free(db->lens, (db->maxmaxcode+1) * sizeof(db->lens[0])); - kmem_free(db, db->totlen); + FREE(db->lens, (db->maxmaxcode+1) * sizeof(db->lens[0])); + FREE(db, db->totlen); } static void * @@ -369,10 +427,10 @@ bsd_decomp_alloc(options, opt_len) * Initialize the database. */ static int -bsd_init(db, options, opt_len, unit, mru, debug, decomp) +bsd_init(db, options, opt_len, unit, hdrlen, mru, debug, decomp) struct bsd_db *db; u_char *options; - int opt_len, unit, mru, debug, decomp; + int opt_len, unit, hdrlen, mru, debug, decomp; { int i; @@ -394,12 +452,12 @@ bsd_init(db, options, opt_len, unit, mru, debug, decomp) } db->unit = unit; + db->hdrlen = hdrlen; db->mru = mru; - db->clear_count = -1; if (debug) db->debug = 1; - bsd_clear(db); + bsd_reset(db); return 1; } @@ -411,21 +469,20 @@ bsd_comp_init(state, options, opt_len, unit, debug) int opt_len, unit, debug; { return bsd_init((struct bsd_db *) state, options, opt_len, - unit, 0, debug, 0); + unit, 0, 0, debug, 0); } static int -bsd_decomp_init(state, options, opt_len, unit, mru, debug) +bsd_decomp_init(state, options, opt_len, unit, hdrlen, mru, debug) void *state; u_char *options; - int opt_len, unit, mru, debug; + int opt_len, unit, hdrlen, mru, debug; { return bsd_init((struct bsd_db *) state, options, opt_len, - unit, mru, debug, 1); + unit, hdrlen, mru, debug, 1); } - /* * compress a packet * One change from the BSD compress command is that when the @@ -447,7 +504,7 @@ bsd_compress(state, mretp, mp, slen, maxolen) u_int32_t accm = 0, fcode; struct bsd_dict *dictp; u_char c; - int hval, disp, ent; + int hval, disp, ent, ilen; mblk_t *np, *mret; u_char *rptr, *wptr; u_char *cp_end; @@ -541,7 +598,7 @@ bsd_compress(state, mretp, mp, slen, maxolen) rptr += PPP_HDRLEN; slen = mp->b_wptr - rptr; - db->in_count += slen + 1; + ilen = slen + 1; np = mp->b_cont; for (;;) { if (slen <= 0) { @@ -552,7 +609,7 @@ bsd_compress(state, mretp, mp, slen, maxolen) np = np->b_cont; if (!slen) continue; /* handle 0-length buffers */ - db->in_count += slen; + ilen += slen; } slen--; @@ -579,7 +636,7 @@ bsd_compress(state, mretp, mp, slen, maxolen) if (dictp->codem1 >= max_ent) goto nomatch; } while (dictp->f.fcode != fcode); - ent = dictp->codem1+1; /* finally found (prefix,suffix) */ + ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */ continue; nomatch: @@ -607,11 +664,14 @@ bsd_compress(state, mretp, mp, slen, maxolen) ent = c; } - OUTPUT(ent); /* output the last code */ + OUTPUT(ent); /* output the last code */ db->bytes_out += olen; + db->in_count += ilen; + if (bitno < 32) + ++db->bytes_out; /* count complete bytes */ if (bsd_check(db)) - OUTPUT(CLEAR); /* do not count the CLEAR */ + OUTPUT(CLEAR); /* do not count the CLEAR */ /* * Pad dribble bits of last code with ones. @@ -627,16 +687,22 @@ bsd_compress(state, mretp, mp, slen, maxolen) if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) db->n_bits++; + db->uncomp_bytes += ilen; + ++db->uncomp_count; if (olen + PPP_HDRLEN + BSD_OVHD > maxolen && mret != NULL) { /* throw away the compressed stuff if it is longer than uncompressed */ freemsg(mret); mret = NULL; + ++db->incomp_count; + db->incomp_bytes += ilen; } else if (wptr != NULL) { m->b_wptr = wptr; if (m->b_cont) { freemsg(m->b_cont); m->b_cont = NULL; } + ++db->comp_count; + db->comp_bytes += olen + BSD_OVHD; } *mretp = mret; @@ -663,7 +729,7 @@ bsd_incomp(state, dmsg) u_int32_t fcode; u_char c; long hval, disp; - int slen; + int slen, ilen; u_int bitno = 7; u_char *rptr; u_int ent; @@ -680,7 +746,7 @@ bsd_incomp(state, dmsg) db->incomp_count++; db->seqno++; - db->in_count++; /* count the protocol as 1 byte */ + ilen = 1; /* count the protocol as 1 byte */ rptr += PPP_HDRLEN; for (;;) { slen = dmsg->b_wptr - rptr; @@ -691,7 +757,7 @@ bsd_incomp(state, dmsg) rptr = dmsg->b_rptr; continue; /* skip zero-length buffers */ } - db->in_count += slen; + ilen += slen; do { c = *rptr++; @@ -748,8 +814,14 @@ bsd_incomp(state, dmsg) } bitno += n_bits; /* output (count) the last code */ db->bytes_out += bitno/8; + db->in_count += ilen; (void)bsd_check(db); + ++db->incomp_count; + db->incomp_bytes += ilen; + ++db->uncomp_count; + db->uncomp_bytes += ilen; + /* Increase code size if we would have without the packet * boundary and as the decompressor will. */ @@ -760,6 +832,19 @@ bsd_incomp(state, dmsg) /* * Decompress "BSD Compress" + * + * Because of patent problems, we return DECOMP_ERROR for errors + * found by inspecting the input data and for system problems, but + * DECOMP_FATALERROR for any errors which could possibly be said to + * be being detected "after" decompression. For DECOMP_ERROR, + * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be + * infringing a patent of Motorola's if we do, so we take CCP down + * instead. + * + * Given that the frame has the correct sequence number and a good FCS, + * errors such as invalid codes in the input most likely indicate a + * bug, so we return DECOMP_FATALERROR for them in order to turn off + * compression, even though they are detected by inspecting the input. */ static int bsd_decompress(state, cmsg, dmpp) @@ -777,7 +862,7 @@ bsd_decompress(state, cmsg, dmpp) u_int incode, oldcode, finchar; u_char *p, *rptr, *wptr; mblk_t *dmsg, *mret; - int adrs, ctrl; + int adrs, ctrl, ilen; int dlen, space, codelen, extra; /* @@ -802,7 +887,7 @@ bsd_decompress(state, cmsg, dmpp) rptr += PPP_HDRLEN; seq = (rptr[0] << 8) + rptr[1]; rptr += BSD_OVHD; - len = cmsg->b_wptr - rptr; + ilen = len = cmsg->b_wptr - rptr; /* * Check the sequence number and give up if it is not what we expect. @@ -817,9 +902,10 @@ bsd_decompress(state, cmsg, dmpp) /* * Allocate one message block to start with. */ - if ((dmsg = allocb(DECOMP_CHUNK, BPRI_MED)) == NULL) + if ((dmsg = allocb(DECOMP_CHUNK + db->hdrlen, BPRI_MED)) == NULL) return DECOMP_ERROR; mret = dmsg; + dmsg->b_wptr += db->hdrlen; dmsg->b_rptr = wptr = dmsg->b_wptr; /* Fill in the ppp header, but not the last byte of the protocol @@ -830,7 +916,6 @@ bsd_decompress(state, cmsg, dmpp) wptr += PPP_HDRLEN - 1; space = dmsg->b_datap->db_lim - wptr; - db->bytes_out += len; oldcode = CLEAR; explen = 0; for (;;) { @@ -840,7 +925,7 @@ bsd_decompress(state, cmsg, dmpp) break; rptr = cmsg->b_rptr; len = cmsg->b_wptr - rptr; - db->bytes_out += len; + ilen += len; continue; /* handle 0-length buffers */ } @@ -875,11 +960,11 @@ bsd_decompress(state, cmsg, dmpp) } } bsd_clear(db); - explen = 0; + explen = ilen = 0; break; } - if (incode > max_ent+2 || incode > db->maxmaxcode + if (incode > max_ent + 2 || incode > db->maxmaxcode || incode > max_ent && oldcode == CLEAR) { freemsg(dmsg); if (db->debug) { @@ -888,7 +973,7 @@ bsd_decompress(state, cmsg, dmpp) printf("max_ent=0x%x dlen=%d seqno=%d\n", max_ent, dlen, db->seqno); } - return DECOMP_FATALERROR; + return DECOMP_FATALERROR; /* probably a bug */ } /* Special case for KwKwK string. */ @@ -1018,12 +1103,18 @@ bsd_decompress(state, cmsg, dmpp) * Keep the checkpoint right so that incompressible packets * clear the dictionary at the right times. */ + db->bytes_out += ilen; db->in_count += explen; if (bsd_check(db) && db->debug) { printf("bsd_decomp%d: peer should have cleared dictionary\n", db->unit); } + ++db->comp_count; + db->comp_bytes += ilen + BSD_OVHD; + ++db->uncomp_count; + db->uncomp_bytes += explen; + *dmpp = mret; return DECOMP_OK; }