?? compress.c
字號(hào):
/* @(#) pSOSystem/PowerPC V2.1.2: drivers/slip/compress.c 1.4 95/07/25 13:53:25 */
/************************************************************************/
/* */
/* MODULE: slcompress.c */
/* PRODUCT: pNA+ */
/* PURPOSE: Van Jacobson header compression */
/* DATE: 93/12/01 */
/* */
/*----------------------------------------------------------------------*/
/* */
/* Copyright 1993, Integrated Systems Inc. */
/* ALL RIGHTS RESERVED */
/* */
/* This computer program is the property of Integrated Systems Inc. */
/* Santa Clara, California, U.S.A. and may not be copied */
/* in any form or by any means, whether in part or in whole, */
/* except under license expressly granted by Integrated Systems Inc. */
/* */
/* All copies of this program, whether in part or in whole, and */
/* whether modified or not, must display this and all other */
/* embedded copyright and ownership notices in full. */
/* */
/*----------------------------------------------------------------------*/
/* */
/* Global Procedures: */
/* */
/* */
/************************************************************************/
/*
* Routines to compress and uncompess tcp packets (for transmission
* over low speed serial lines.
*
* Copyright (c) 1989, 1991 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Van Jacobson (van@ee.lbl.gov), Dec 31, 1989:
* - Initial distribution.
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: compress.c,v 1.1 97/07/23 10:26:40 kapil Exp $ (LBL)";
#endif
#include <string.h>
#include "bsp.h"
#include "pna.h"
#include "ppp.h"
#include "compress.h"
#ifndef SL_NO_STATS
#define INCR(counter) (++comp->counter)
#else
#define INCR(counter) ((void) 0)
#endif
/*#define BCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n))*/
/*#define BCOPY(p1, p2, n) slbcopy((U_CHAR *)(p1), (U_CHAR *)(p2), (int)(n))*/
/*#ifndef KERNEL
#define ovbcopy slbcopy
#endif*/
#define BCMP(p0, p1, n) memcmp (p0, p1, n)
#define BCOPY(p0, p1, n) memmove (p1, p0, n)
#define ovbcopy(p0, p1, n) memmove (p1, p0, n)
/*
* sizeof(word) MUST BE A POWER OF TWO
* SO THAT wmask BELOW IS ALL ONES
*/
typedef int word; /* "word" used for optimal copy speed */
#define wsize sizeof(word)
#define wmask (wsize - 1)
/*----------------------------------------------------------------------*/
/* prototypes */
/*----------------------------------------------------------------------*/
/*static int bcmp(char *b1, char *b2, int n);*/
/*extern void bzero(char *cp, long size);*/
#if 0
/************************************************************************/
/* slbcopy: BSD style byte copying */
/* INPUTS: b1 - source, b2 - dest, n - length */
/* RETURNS: */
/* OUTPUTS: */
/* NOTE(S): Handles overlap. */
/************************************************************************/
void
slbcopy(U_CHAR *src0, U_CHAR *dst0, int length)
{
register U_CHAR *dst = dst0;
register const U_CHAR *src = src0;
register int t;
if (length == 0 || dst == src) /* nothing to do */
return;
/*
* Macros: loop-t-times; and loop-t-times, t>0
*/
#define TLOOP(s) if (t) TLOOP1(s)
#define TLOOP1(s) do { s; } while (--t)
if ((unsigned long)dst < (unsigned long)src) {
/*
* Copy forward.
*/
t = (int)src; /* only need low bits */
if ((t | (int)dst) & wmask) {
/*
* Try to align operands. This cannot be done
* unless the low bits match.
*/
if ((t ^ (int)dst) & wmask || length < wsize)
t = length;
else
t = wsize - (t & wmask);
length -= t;
TLOOP1(*dst++ = *src++);
}
/*
* Copy whole words, then mop up any trailing bytes.
*/
t = length / wsize;
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
t = length & wmask;
TLOOP(*dst++ = *src++);
} else {
/*
* Copy backwards. Otherwise essentially the same.
* Alignment works as before, except that it takes
* (t&wmask) bytes to align, not wsize-(t&wmask).
*/
src += length;
dst += length;
t = (int)src;
if ((t | (int)dst) & wmask) {
if ((t ^ (int)dst) & wmask || length <= wsize)
t = length;
else
t &= wmask;
length -= t;
TLOOP1(*--dst = *--src);
}
t = length / wsize;
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
t = length & wmask;
TLOOP(*--dst = *--src);
}
}
#endif
#if 0
/************************************************************************/
/* bcmp : BSD-style string comparison (of same length) */
/* INPUTS: b1 - string1; b2 - string2; n - size */
/* RETURNS: */
/* OUTPUTS: 0 - identical; nonzero otherwise */
/* NOTE(S): */
/************************************************************************/
static int bcmp(char *b1, char *b2, int n)
{
if (!n) return 0;
while (n--)
{
if (*b1++ != *b2++) return 1;
}
return 0;
}
#endif
void
sl_compress_init(struct slcompress *comp)
{
register U_INT i;
register struct cstate *tstate = comp->tstate;
bzero((char *)comp, sizeof(*comp));
for (i = MAX_STATES - 1; i > 0; --i) {
tstate[i].cs_id = i;
tstate[i].cs_next = &tstate[i - 1];
}
tstate[0].cs_next = &tstate[MAX_STATES - 1];
tstate[0].cs_id = 0;
comp->last_cs = &tstate[0];
comp->last_recv = 255;
comp->last_xmit = 255;
comp->flags = SLF_TOSS;
}
/* ENCODE encodes a number that is known to be non-zero. ENCODEZ
* checks for zero (since zero has to be encoded in the long, 3 byte
* form).
*/
#define ENCODE(n) { \
if ((U_SHORT)(n) >= 256) { \
*cp++ = 0; \
cp[1] = (n); \
cp[0] = (n) >> 8; \
cp += 2; \
} else { \
*cp++ = (n); \
} \
}
#define ENCODEZ(n) { \
if ((U_SHORT)(n) >= 256 || (U_SHORT)(n) == 0) { \
*cp++ = 0; \
cp[1] = (n); \
cp[0] = (n) >> 8; \
cp += 2; \
} else { \
*cp++ = (n); \
} \
}
#define DECODEL(f) { \
if (*cp == 0) {\
(f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \
cp += 3; \
} else { \
(f) = htonl(ntohl(f) + (U_LONG)*cp++); \
} \
}
#define DECODES(f) { \
if (*cp == 0) {\
(f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \
cp += 3; \
} else { \
(f) = htons(ntohs(f) + (U_LONG)*cp++); \
} \
}
#define DECODEU(f) { \
if (*cp == 0) {\
(f) = htons((cp[1] << 8) | cp[2]); \
cp += 3; \
} else { \
(f) = htons((U_LONG)*cp++); \
} \
}
U_CHAR
sl_compress_tcp(struct mbuf *m, struct ip *ip, struct slcompress *comp,
int compress_cid)
{
register struct cstate *cs = comp->last_cs->cs_next;
register U_INT hlen = ip->ip_hl;
register struct tcphdr *oth;
register struct tcphdr *th;
register U_INT deltaS, deltaA;
register U_INT changes = 0;
U_CHAR new_seq[16];
register U_CHAR *cp = new_seq;
/*
* Bail if this is an IP fragment or if the TCP packet isn't
* `compressible' (i.e., ACK isn't set or some other control bit is
* set). (We assume that the caller has already made sure the
* packet is IP proto TCP).
*/
if ((ip->ip_off & htons(0x3fff)) || m->m_len < 40)
return (TYPE_IP);
th = (struct tcphdr *)&((int *)ip)[hlen];
if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
return (TYPE_IP);
/*
* Packet is compressible -- we're going to send either a
* COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need
* to locate (or create) the connection state. Special case the
* most recently used connection since it's most likely to be used
* again & we don't have to do any reordering if it's used.
*/
INCR(sls_packets);
if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
*(int *)th != ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl]) {
/*
* Wasn't the first -- search for it.
*
* States are kept in a circularly linked list with
* last_cs pointing to the end of the list. The
* list is kept in lru order by moving a state to the
* head of the list whenever it is referenced. Since
* the list is short and, empirically, the connection
* we want is almost always near the front, we locate
* states via linear search. If we don't find a state
* for the datagram, the oldest state is (re-)used.
*/
register struct cstate *lcs;
register struct cstate *lastcs = comp->last_cs;
do {
lcs = cs; cs = cs->cs_next;
INCR(sls_searches);
if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
&& ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
&& *(int *)th == ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl])
goto found;
} while (cs != lastcs);
/*
* Didn't find it -- re-use oldest cstate. Send an
* uncompressed packet that tells the other side what
* connection number we're using for this conversation.
* Note that since the state list is circular, the oldest
* state points to the newest and we only need to set
* last_cs to update the lru linkage.
*/
INCR(sls_misses);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -