This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
dexter gerrit-no-reply at lists.osmocom.orgReview at https://gerrit.osmocom.org/635 Modifed version of slhc Change-Id: I7a638e88a43b3eb9d006751a03ef2570e36613f0 --- M openbsc/include/openbsc/debug.h R openbsc/include/openbsc/slhc.h M openbsc/src/gprs/Makefile.am M openbsc/src/gprs/slhc.c 4 files changed, 127 insertions(+), 176 deletions(-) git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/35/635/1 diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h index 43ebb19..90ddca5 100644 --- a/openbsc/include/openbsc/debug.h +++ b/openbsc/include/openbsc/debug.h @@ -29,6 +29,7 @@ DBSSGP, DLLC, DSNDCP, + DSLHC, DNAT, DCTRL, DSMPP, diff --git a/openbsc/include/openbsc/slhc_vj.h b/openbsc/include/openbsc/slhc.h similarity index 89% rename from openbsc/include/openbsc/slhc_vj.h rename to openbsc/include/openbsc/slhc.h index 0a85dc0..2e926dd 100644 --- a/openbsc/include/openbsc/slhc_vj.h +++ b/openbsc/include/openbsc/slhc.h @@ -80,7 +80,6 @@ * means "IP packet". */ - #include <linux/ip.h> #include <linux/tcp.h> @@ -109,7 +108,7 @@ * data type and sizes conversion assumptions: * * VJ code KA9Q style generic - * u_char byte_t unsigned char 8 bits + * u_char byte_t uint8_t 8 bits * u_short int16 unsigned short 16 bits * u_int int16 unsigned short 16 bits * u_long unsigned long unsigned long 32 bits @@ -130,8 +129,8 @@ struct cstate *next; /* next in ring (xmit) */ struct iphdr cs_ip; /* ip/tcp hdr from most recent packet */ struct tcphdr cs_tcp; - unsigned char cs_ipopt[64]; - unsigned char cs_tcpopt[64]; + uint8_t cs_ipopt[64]; + uint8_t cs_tcpopt[64]; int cs_hsize; }; #define NULLSLSTATE (struct cstate *)0 @@ -173,19 +172,16 @@ #define __ARGS(x) x /* In slhc.c: */ -struct slcompress *slhc_init __ARGS((int rslots, int tslots)); -void slhc_free __ARGS((struct slcompress *comp)); +struct slcompress *slhc_init(int rslots, int tslots); -int slhc_compress __ARGS((struct slcompress *comp, unsigned char *icp, - int isize, unsigned char *ocp, unsigned char **cpp, - int compress_cid)); -int slhc_uncompress __ARGS((struct slcompress *comp, unsigned char *icp, - int isize)); -int slhc_remember __ARGS((struct slcompress *comp, unsigned char *icp, - int isize)); -int slhc_toss __ARGS((struct slcompress *comp)); +void slhc_free(struct slcompress *comp); -void slhc_i_status __ARGS((struct slcompress *comp)); -void slhc_o_status __ARGS((struct slcompress *comp)); +int slhc_compress(struct slcompress *comp, uint8_t *icp, int isize, uint8_t *ocp, uint8_t **cpp, int compress_cid); +int slhc_uncompress(struct slcompress *comp, uint8_t *icp, int isize); +int slhc_remember(struct slcompress *comp, uint8_t *icp, int isize); +int slhc_toss(struct slcompress *comp); + +void slhc_i_status(struct slcompress *comp); +void slhc_o_status(struct slcompress *comp); #endif /* _SLHC_H */ diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index 6dc7e16..548b38c 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -23,6 +23,7 @@ $(OSMO_LIBS) $(LIBCRYPTO_LIBS) -lrt osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ + slhc.c \ sgsn_main.c sgsn_vty.c sgsn_libgtp.c \ gprs_llc.c gprs_llc_parse.c gprs_llc_vty.c crc24.c \ sgsn_ctrl.c sgsn_auth.c gprs_subscriber.c \ diff --git a/openbsc/src/gprs/slhc.c b/openbsc/src/gprs/slhc.c index b1a855c..b201ddb 100644 --- a/openbsc/src/gprs/slhc.c +++ b/openbsc/src/gprs/slhc.c @@ -50,62 +50,71 @@ * driver code belonging close to PPP and SLIP */ -#include <linux/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <net/slhc_vj.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <arpa/inet.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/talloc.h> +#include <openbsc/slhc.h> +#include <openbsc/debug.h> -#ifdef CONFIG_INET -/* Entire module is for IP only */ -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/socket.h> -#include <linux/sockios.h> -#include <linux/termios.h> -#include <linux/in.h> -#include <linux/fcntl.h> -#include <linux/inet.h> -#include <linux/netdevice.h> -#include <net/ip.h> -#include <net/protocol.h> -#include <net/icmp.h> -#include <net/tcp.h> -#include <linux/skbuff.h> -#include <net/sock.h> -#include <linux/timer.h> -#include <asm/system.h> -#include <asm/uaccess.h> -#include <net/checksum.h> -#include <asm/unaligned.h> +static uint8_t *encode(uint8_t *cp, uint16_t n); +static long decode(uint8_t **cpp); +static uint8_t * put16(uint8_t *cp, uint16_t x); +static uint16_t pull16(uint8_t **cpp); -static unsigned char *encode(unsigned char *cp, unsigned short n); -static long decode(unsigned char **cpp); -static unsigned char * put16(unsigned char *cp, unsigned short x); -static unsigned short pull16(unsigned char **cpp); + +/* Replacement for kernel space function ip_fast_csum() */ +static uint16_t ip_fast_csum(uint8_t *iph, int ihl) +{ + int i; + uint16_t temp; + uint32_t accumulator = 0xFFFF; + + for(i=0;i<ihl*2;i++) + { + temp = ((*iph) << 8)&0xFF00; + iph++; + temp |= (*iph)&0xFF; + iph++; + + accumulator+=temp; + if(accumulator>0xFFFF) + { + accumulator++; + accumulator&=0xFFFF; + } + } + + return (uint16_t)(htons(~accumulator)&0xFFFF); +} + +/* Replacement for kernel space function put_unaligned() */ +static void put_unaligned(uint16_t val, void *ptr) +{ + memcpy(ptr,&val,sizeof(val)); +} + /* Initialize compression data structure * slots must be in range 0 to 255 (zero meaning no compression) */ -struct slcompress * -slhc_init(int rslots, int tslots) +struct slcompress *slhc_init(int rslots, int tslots) { register short i; register struct cstate *ts; struct slcompress *comp; - MOD_INC_USE_COUNT; - comp = (struct slcompress *)kmalloc(sizeof(struct slcompress), - GFP_KERNEL); + comp = (struct slcompress *)talloc_zero_size(NULL,sizeof(struct slcompress)); if (! comp) goto out_fail; memset(comp, 0, sizeof(struct slcompress)); if ( rslots > 0 && rslots < 256 ) { size_t rsize = rslots * sizeof(struct cstate); - comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL); + comp->rstate = (struct cstate *) talloc_zero_size(NULL, rsize); if (! comp->rstate) goto out_free; memset(comp->rstate, 0, rsize); @@ -114,7 +123,7 @@ if ( tslots > 0 && tslots < 256 ) { size_t tsize = tslots * sizeof(struct cstate); - comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL); + comp->tstate = (struct cstate *) talloc_zero_size(NULL, tsize); if (! comp->tstate) goto out_free2; memset(comp->tstate, 0, tsize); @@ -144,36 +153,34 @@ return comp; out_free2: - kfree((unsigned char *)comp->rstate); + talloc_free((uint8_t *)comp->rstate); out_free: - kfree((unsigned char *)comp); + talloc_free((uint8_t *)comp); out_fail: - MOD_DEC_USE_COUNT; + + return NULL; } - /* Free a compression data structure */ -void -slhc_free(struct slcompress *comp) +void slhc_free(struct slcompress *comp) { + LOGP(DSLHC, LOGL_DEBUG, "slhc_free(): Freeing compression states...\n"); + if ( comp == NULLSLCOMPR ) return; if ( comp->tstate != NULLSLSTATE ) - kfree( comp->tstate ); + talloc_free(comp->tstate ); if ( comp->rstate != NULLSLSTATE ) - kfree( comp->rstate ); + talloc_free( comp->rstate ); - kfree( comp ); - MOD_DEC_USE_COUNT; + talloc_free( comp ); } - /* Put a short in host order into a char array in network order */ -static inline unsigned char * -put16(unsigned char *cp, unsigned short x) +static inline uint8_t *put16(uint8_t *cp, uint16_t x) { *cp++ = x >> 8; *cp++ = x; @@ -183,8 +190,7 @@ /* Encode a number */ -unsigned char * -encode(unsigned char *cp, unsigned short n) +uint8_t *encode(uint8_t *cp, uint16_t n) { if(n >= 256 || n == 0){ *cp++ = 0; @@ -196,8 +202,7 @@ } /* Pull a 16-bit integer in host order from buffer in network byte order */ -static unsigned short -pull16(unsigned char **cpp) +static uint16_t pull16(uint8_t **cpp) { short rval; @@ -208,8 +213,7 @@ } /* Decode a number */ -long -decode(unsigned char **cpp) +long decode(uint8_t **cpp) { register int x; @@ -228,9 +232,7 @@ * change it to ocp. */ -int -slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, - unsigned char *ocp, unsigned char **cpp, int compress_cid) +int slhc_compress(struct slcompress *comp, uint8_t *icp, int isize, uint8_t *ocp, uint8_t **cpp, int compress_cid) { register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]); register struct cstate *lcs = ocs; @@ -238,11 +240,10 @@ register unsigned long deltaS, deltaA; register short changes = 0; int hlen; - unsigned char new_seq[16]; - register unsigned char *cp = new_seq; + uint8_t new_seq[16]; + register uint8_t *cp = new_seq; struct iphdr *ip; struct tcphdr *th, *oth; - /* * Don't play with runt packets. @@ -260,11 +261,12 @@ comp->sls_o_nontcp++; else comp->sls_o_tcp++; + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Not a TCP packat, will not touch...\n"); return isize; } - /* Extract TCP header */ - th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4); + /* Extract TCP header */ + th = (struct tcphdr *)(((uint8_t *)ip) + ip->ihl*4); hlen = ip->ihl*4 + th->doff*4; /* Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or @@ -275,8 +277,10 @@ ! (th->ack)){ /* TCP connection stuff; send as regular IP */ comp->sls_o_tcp++; + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Packet is part of a TCP connection, will not touch...\n"); return isize; } + /* * Packet is compressible -- we're going to send either a * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way, @@ -291,6 +295,9 @@ * states via linear search. If we don't find a state * for the datagram, the oldest state is (re-)used. */ + + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Compressible packet detected!\n"); + for ( ; ; ) { if( ip->saddr == cs->cs_ip.saddr && ip->daddr == cs->cs_ip.daddr @@ -314,11 +321,14 @@ * state points to the newest and we only need to set * xmit_oldest to update the lru linkage. */ + + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Header not yet seen, will memorize header for the next turn...\n"); comp->sls_o_misses++; comp->xmit_oldest = lcs->cs_this; goto uncompressed; found: + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Header already seen, trying to compress...\n"); /* * Found it -- move to the front on the connection list. */ @@ -348,6 +358,7 @@ */ oth = &cs->cs_tcp; + if(ip->version != cs->cs_ip.version || ip->ihl != cs->cs_ip.ihl || ip->tos != cs->cs_ip.tos || (ip->frag_off & htons(0x4000)) != (cs->cs_ip.frag_off & htons(0x4000)) @@ -355,6 +366,7 @@ || th->doff != cs->cs_tcp.doff || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0) || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0)){ + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): The header contains unexpected changes, can't compress...\n"); goto uncompressed; } @@ -373,6 +385,7 @@ * implementation should never do this but RFC793 * doesn't prohibit the change so we have to deal * with it. */ + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): URG not set but urp changed, can't compress...\n"); goto uncompressed; } if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){ @@ -381,13 +394,19 @@ } if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){ if(deltaA > 0x0000ffff) + { + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): (deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L, can't compress...\n"); goto uncompressed; + } cp = encode(cp,deltaA); changes |= NEW_A; } if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){ if(deltaS > 0x0000ffff) + { + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): (deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L, can't compress...\n"); goto uncompressed; + } cp = encode(cp,deltaS); changes |= NEW_S; } @@ -403,6 +422,7 @@ if(ip->tot_len != cs->cs_ip.tot_len && ntohs(cs->cs_ip.tot_len) == hlen) break; + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Retransmitted packet detected, can't compress...\n"); goto uncompressed; break; case SPECIAL_I: @@ -410,6 +430,7 @@ /* actual changes match one of our special case encodings -- * send packet uncompressed. */ + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Special case detected, can't compress...\n"); goto uncompressed; case NEW_S|NEW_A: if(deltaS == deltaA && @@ -438,7 +459,6 @@ * state with this packet's header. */ deltaA = ntohs(th->check); - memcpy(&cs->cs_ip,ip,20); memcpy(&cs->cs_tcp,th,20); /* We want to use the original packet as our compressed packet. * (cp - new_seq) is the number of bytes we need for compressed @@ -471,6 +491,7 @@ * to use on future compressed packets in the protocol field). */ uncompressed: + LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Packet will be sent uncompressed...\n"); memcpy(&cs->cs_ip,ip,20); memcpy(&cs->cs_tcp,th,20); if (ip->ihl > 5) @@ -487,8 +508,7 @@ } -int -slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) +int slhc_uncompress(struct slcompress *comp, uint8_t *icp, int isize) { register int changes; long x; @@ -496,7 +516,7 @@ register struct iphdr *ip; register struct cstate *cs; int len, hdrlen; - unsigned char *cp = icp; + uint8_t *cp = icp; /* We've got a compressed packet; read the change byte */ comp->sls_i_compressed++; @@ -544,6 +564,8 @@ switch(changes & SPECIALS_MASK){ case SPECIAL_I: /* Echoed terminal traffic */ + LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): Echoed terminal traffic detected\n"); + { register short i; i = ntohs(ip->tot_len) - hdrlen; @@ -553,11 +575,13 @@ break; case SPECIAL_D: /* Unidirectional data */ + LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): Unidirectional data detected\n"); thp->seq = htonl( ntohl(thp->seq) + ntohs(ip->tot_len) - hdrlen); break; default: + LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): default packet type detected\n"); if(changes & NEW_U){ thp->urg = 1; if((x = decode(&cp)) == -1) { @@ -607,6 +631,7 @@ ip->tot_len = htons(len); ip->check = 0; + LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): making space for the reconstructed header...\n"); memmove(icp + hdrlen, cp, len - hdrlen); cp = icp; @@ -618,8 +643,7 @@ cp += (ip->ihl - 5) * 4; } - put_unaligned(ip_fast_csum(icp, ip->ihl), - &((struct iphdr *)icp)->check); + put_unaligned(ip_fast_csum(icp, ip->ihl), &((struct iphdr *)icp)->check); memcpy(cp, thp, 20); cp += 20; @@ -631,22 +655,24 @@ return len; bad: + LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): bad packet detected!\n"); comp->sls_i_error++; return slhc_toss( comp ); } -int -slhc_remember(struct slcompress *comp, unsigned char *icp, int isize) +int slhc_remember(struct slcompress *comp, uint8_t *icp, int isize) { register struct cstate *cs; unsigned ihl; - unsigned char index; + uint8_t index; + uint16_t checksum; if(isize < 20) { /* The packet is shorter than a legal IP header */ comp->sls_i_runt++; + LOGP(DSLHC, LOGL_DEBUG, "slhc_remember(): The packet is shorter than a legal IP header ==> slhc_toss()\n"); return slhc_toss( comp ); } /* Peek at the IP header's IHL field to find its length */ @@ -654,18 +680,23 @@ if(ihl < 20 / 4){ /* The IP header length field is too small */ comp->sls_i_runt++; + LOGP(DSLHC, LOGL_DEBUG, "slhc_remember(): The IP header length field is too small ==> slhc_toss()\n"); return slhc_toss( comp ); } + index = icp[9]; icp[9] = IPPROTO_TCP; + checksum = ip_fast_csum(icp, ihl); - if (ip_fast_csum(icp, ihl)) { + if (checksum) { /* Bad IP header checksum; discard */ comp->sls_i_badcheck++; + LOGP(DSLHC, LOGL_DEBUG, "slhc_remember(): Bad IP header checksum; discard ==> slhc_toss()\n"); return slhc_toss( comp ); } if(index > comp->rslot_limit) { comp->sls_i_error++; + LOGP(DSLHC, LOGL_DEBUG, "slhc_remember(): index > comp->rslot_limit ==> slhc_toss()\n"); return slhc_toss(comp); } @@ -686,10 +717,9 @@ return isize; } - -int -slhc_toss(struct slcompress *comp) +int slhc_toss(struct slcompress *comp) { + LOGP(DSLHC, LOGL_DEBUG, "slhc_toss(): Reset compression state...\n"); if ( comp == NULLSLCOMPR ) return 0; @@ -697,11 +727,10 @@ return 0; } - void slhc_i_status(struct slcompress *comp) { if (comp != NULLSLCOMPR) { - printk("\t%d Cmp, %d Uncmp, %d Bad, %d Tossed\n", + LOGP(DSLHC, LOGL_DEBUG, "slhc_i_status(): %d Cmp, %d Uncmp, %d Bad, %d Tossed\n", comp->sls_i_compressed, comp->sls_i_uncompressed, comp->sls_i_error, @@ -709,92 +738,16 @@ } } - void slhc_o_status(struct slcompress *comp) { if (comp != NULLSLCOMPR) { - printk("\t%d Cmp, %d Uncmp, %d AsIs, %d NotTCP\n", + LOGP(DSLHC, LOGL_DEBUG, "slhc_o_status(): %d Cmp, %d Uncmp, %d AsIs, %d NotTCP %d Searches, %d Misses\n", comp->sls_o_compressed, comp->sls_o_uncompressed, comp->sls_o_tcp, - comp->sls_o_nontcp); - printk("\t%10d Searches, %10d Misses\n", + comp->sls_o_nontcp, comp->sls_o_searches, comp->sls_o_misses); } } -/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */ -/* VJ header compression */ -EXPORT_SYMBOL(slhc_init); -EXPORT_SYMBOL(slhc_free); -EXPORT_SYMBOL(slhc_remember); -EXPORT_SYMBOL(slhc_compress); -EXPORT_SYMBOL(slhc_uncompress); -EXPORT_SYMBOL(slhc_toss); - -#ifdef MODULE - -int init_module(void) -{ - printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California\n"); - return 0; -} - -void cleanup_module(void) -{ - return; -} - -#endif /* MODULE */ -#else /* CONFIG_INET */ - - -int -slhc_toss(struct slcompress *comp) -{ - printk(KERN_DEBUG "Called IP function on non IP-system: slhc_toss"); - return -EINVAL; -} -int -slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) -{ - printk(KERN_DEBUG "Called IP function on non IP-system: slhc_uncompress"); - return -EINVAL; -} -int -slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, - unsigned char *ocp, unsigned char **cpp, int compress_cid) -{ - printk(KERN_DEBUG "Called IP function on non IP-system: slhc_compress"); - return -EINVAL; -} - -int -slhc_remember(struct slcompress *comp, unsigned char *icp, int isize) -{ - printk(KERN_DEBUG "Called IP function on non IP-system: slhc_remember"); - return -EINVAL; -} - -void -slhc_free(struct slcompress *comp) -{ - printk(KERN_DEBUG "Called IP function on non IP-system: slhc_free"); - return; -} -struct slcompress * -slhc_init(int rslots, int tslots) -{ - printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init"); - return NULL; -} -EXPORT_SYMBOL(slhc_init); -EXPORT_SYMBOL(slhc_free); -EXPORT_SYMBOL(slhc_remember); -EXPORT_SYMBOL(slhc_compress); -EXPORT_SYMBOL(slhc_uncompress); -EXPORT_SYMBOL(slhc_toss); - -#endif /* CONFIG_INET */ -MODULE_LICENSE("Dual BSD/GPL"); -- To view, visit https://gerrit.osmocom.org/635 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I7a638e88a43b3eb9d006751a03ef2570e36613f0 Gerrit-PatchSet: 1 Gerrit-Project: openbsc Gerrit-Branch: master Gerrit-Owner: dexter <pmaier at sysmocom.de>