ia64/linux-2.6.18-xen.hg

view drivers/net/slhc.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /*
2 * Routines to compress and uncompress tcp packets (for transmission
3 * over low speed serial lines).
4 *
5 * Copyright (c) 1989 Regents of the University of California.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the University of California, Berkeley. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
21 * - Initial distribution.
22 *
23 *
24 * modified for KA9Q Internet Software Package by
25 * Katie Stevens (dkstevens@ucdavis.edu)
26 * University of California, Davis
27 * Computing Services
28 * - 01-31-90 initial adaptation (from 1.19)
29 * PPP.05 02-15-90 [ks]
30 * PPP.08 05-02-90 [ks] use PPP protocol field to signal compression
31 * PPP.15 09-90 [ks] improve mbuf handling
32 * PPP.16 11-02 [karn] substantially rewritten to use NOS facilities
33 *
34 * - Feb 1991 Bill_Simpson@um.cc.umich.edu
35 * variable number of conversation slots
36 * allow zero or one slots
37 * separate routines
38 * status display
39 * - Jul 1994 Dmitry Gorodchanin
40 * Fixes for memory leaks.
41 * - Oct 1994 Dmitry Gorodchanin
42 * Modularization.
43 * - Jan 1995 Bjorn Ekwall
44 * Use ip_fast_csum from ip.h
45 * - July 1995 Christos A. Polyzols
46 * Spotted bug in tcp option checking
47 *
48 *
49 * This module is a difficult issue. It's clearly inet code but it's also clearly
50 * driver code belonging close to PPP and SLIP
51 */
53 #include <linux/module.h>
54 #include <linux/types.h>
55 #include <linux/string.h>
56 #include <linux/errno.h>
57 #include <linux/kernel.h>
58 #include <net/slhc_vj.h>
60 #ifdef CONFIG_INET
61 /* Entire module is for IP only */
62 #include <linux/mm.h>
63 #include <linux/socket.h>
64 #include <linux/sockios.h>
65 #include <linux/termios.h>
66 #include <linux/in.h>
67 #include <linux/fcntl.h>
68 #include <linux/inet.h>
69 #include <linux/netdevice.h>
70 #include <net/ip.h>
71 #include <net/protocol.h>
72 #include <net/icmp.h>
73 #include <net/tcp.h>
74 #include <linux/skbuff.h>
75 #include <net/sock.h>
76 #include <linux/timer.h>
77 #include <asm/system.h>
78 #include <asm/uaccess.h>
79 #include <net/checksum.h>
80 #include <asm/unaligned.h>
82 static unsigned char *encode(unsigned char *cp, unsigned short n);
83 static long decode(unsigned char **cpp);
84 static unsigned char * put16(unsigned char *cp, unsigned short x);
85 static unsigned short pull16(unsigned char **cpp);
87 /* Initialize compression data structure
88 * slots must be in range 0 to 255 (zero meaning no compression)
89 */
90 struct slcompress *
91 slhc_init(int rslots, int tslots)
92 {
93 register short i;
94 register struct cstate *ts;
95 struct slcompress *comp;
97 comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
98 GFP_KERNEL);
99 if (! comp)
100 goto out_fail;
101 memset(comp, 0, sizeof(struct slcompress));
103 if ( rslots > 0 && rslots < 256 ) {
104 size_t rsize = rslots * sizeof(struct cstate);
105 comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL);
106 if (! comp->rstate)
107 goto out_free;
108 memset(comp->rstate, 0, rsize);
109 comp->rslot_limit = rslots - 1;
110 }
112 if ( tslots > 0 && tslots < 256 ) {
113 size_t tsize = tslots * sizeof(struct cstate);
114 comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL);
115 if (! comp->tstate)
116 goto out_free2;
117 memset(comp->tstate, 0, tsize);
118 comp->tslot_limit = tslots - 1;
119 }
121 comp->xmit_oldest = 0;
122 comp->xmit_current = 255;
123 comp->recv_current = 255;
124 /*
125 * don't accept any packets with implicit index until we get
126 * one with an explicit index. Otherwise the uncompress code
127 * will try to use connection 255, which is almost certainly
128 * out of range
129 */
130 comp->flags |= SLF_TOSS;
132 if ( tslots > 0 ) {
133 ts = comp->tstate;
134 for(i = comp->tslot_limit; i > 0; --i){
135 ts[i].cs_this = i;
136 ts[i].next = &(ts[i - 1]);
137 }
138 ts[0].next = &(ts[comp->tslot_limit]);
139 ts[0].cs_this = 0;
140 }
141 return comp;
143 out_free2:
144 kfree((unsigned char *)comp->rstate);
145 out_free:
146 kfree((unsigned char *)comp);
147 out_fail:
148 return NULL;
149 }
152 /* Free a compression data structure */
153 void
154 slhc_free(struct slcompress *comp)
155 {
156 if ( comp == NULLSLCOMPR )
157 return;
159 if ( comp->tstate != NULLSLSTATE )
160 kfree( comp->tstate );
162 if ( comp->rstate != NULLSLSTATE )
163 kfree( comp->rstate );
165 kfree( comp );
166 }
169 /* Put a short in host order into a char array in network order */
170 static inline unsigned char *
171 put16(unsigned char *cp, unsigned short x)
172 {
173 *cp++ = x >> 8;
174 *cp++ = x;
176 return cp;
177 }
180 /* Encode a number */
181 unsigned char *
182 encode(unsigned char *cp, unsigned short n)
183 {
184 if(n >= 256 || n == 0){
185 *cp++ = 0;
186 cp = put16(cp,n);
187 } else {
188 *cp++ = n;
189 }
190 return cp;
191 }
193 /* Pull a 16-bit integer in host order from buffer in network byte order */
194 static unsigned short
195 pull16(unsigned char **cpp)
196 {
197 short rval;
199 rval = *(*cpp)++;
200 rval <<= 8;
201 rval |= *(*cpp)++;
202 return rval;
203 }
205 /* Decode a number */
206 long
207 decode(unsigned char **cpp)
208 {
209 register int x;
211 x = *(*cpp)++;
212 if(x == 0){
213 return pull16(cpp) & 0xffff; /* pull16 returns -1 on error */
214 } else {
215 return x & 0xff; /* -1 if PULLCHAR returned error */
216 }
217 }
219 /*
220 * icp and isize are the original packet.
221 * ocp is a place to put a copy if necessary.
222 * cpp is initially a pointer to icp. If the copy is used,
223 * change it to ocp.
224 */
226 int
227 slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
228 unsigned char *ocp, unsigned char **cpp, int compress_cid)
229 {
230 register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
231 register struct cstate *lcs = ocs;
232 register struct cstate *cs = lcs->next;
233 register unsigned long deltaS, deltaA;
234 register short changes = 0;
235 int hlen;
236 unsigned char new_seq[16];
237 register unsigned char *cp = new_seq;
238 struct iphdr *ip;
239 struct tcphdr *th, *oth;
242 /*
243 * Don't play with runt packets.
244 */
246 if(isize<sizeof(struct iphdr))
247 return isize;
249 ip = (struct iphdr *) icp;
251 /* Bail if this packet isn't TCP, or is an IP fragment */
252 if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) {
253 /* Send as regular IP */
254 if(ip->protocol != IPPROTO_TCP)
255 comp->sls_o_nontcp++;
256 else
257 comp->sls_o_tcp++;
258 return isize;
259 }
260 /* Extract TCP header */
262 th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
263 hlen = ip->ihl*4 + th->doff*4;
265 /* Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
266 * some other control bit is set). Also uncompressible if
267 * it's a runt.
268 */
269 if(hlen > isize || th->syn || th->fin || th->rst ||
270 ! (th->ack)){
271 /* TCP connection stuff; send as regular IP */
272 comp->sls_o_tcp++;
273 return isize;
274 }
275 /*
276 * Packet is compressible -- we're going to send either a
277 * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way,
278 * we need to locate (or create) the connection state.
279 *
280 * States are kept in a circularly linked list with
281 * xmit_oldest pointing to the end of the list. The
282 * list is kept in lru order by moving a state to the
283 * head of the list whenever it is referenced. Since
284 * the list is short and, empirically, the connection
285 * we want is almost always near the front, we locate
286 * states via linear search. If we don't find a state
287 * for the datagram, the oldest state is (re-)used.
288 */
289 for ( ; ; ) {
290 if( ip->saddr == cs->cs_ip.saddr
291 && ip->daddr == cs->cs_ip.daddr
292 && th->source == cs->cs_tcp.source
293 && th->dest == cs->cs_tcp.dest)
294 goto found;
296 /* if current equal oldest, at end of list */
297 if ( cs == ocs )
298 break;
299 lcs = cs;
300 cs = cs->next;
301 comp->sls_o_searches++;
302 };
303 /*
304 * Didn't find it -- re-use oldest cstate. Send an
305 * uncompressed packet that tells the other side what
306 * connection number we're using for this conversation.
307 *
308 * Note that since the state list is circular, the oldest
309 * state points to the newest and we only need to set
310 * xmit_oldest to update the lru linkage.
311 */
312 comp->sls_o_misses++;
313 comp->xmit_oldest = lcs->cs_this;
314 goto uncompressed;
316 found:
317 /*
318 * Found it -- move to the front on the connection list.
319 */
320 if(lcs == ocs) {
321 /* found at most recently used */
322 } else if (cs == ocs) {
323 /* found at least recently used */
324 comp->xmit_oldest = lcs->cs_this;
325 } else {
326 /* more than 2 elements */
327 lcs->next = cs->next;
328 cs->next = ocs->next;
329 ocs->next = cs;
330 }
332 /*
333 * Make sure that only what we expect to change changed.
334 * Check the following:
335 * IP protocol version, header length & type of service.
336 * The "Don't fragment" bit.
337 * The time-to-live field.
338 * The TCP header length.
339 * IP options, if any.
340 * TCP options, if any.
341 * If any of these things are different between the previous &
342 * current datagram, we send the current datagram `uncompressed'.
343 */
344 oth = &cs->cs_tcp;
346 if(ip->version != cs->cs_ip.version || ip->ihl != cs->cs_ip.ihl
347 || ip->tos != cs->cs_ip.tos
348 || (ip->frag_off & htons(0x4000)) != (cs->cs_ip.frag_off & htons(0x4000))
349 || ip->ttl != cs->cs_ip.ttl
350 || th->doff != cs->cs_tcp.doff
351 || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0)
352 || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0)){
353 goto uncompressed;
354 }
356 /*
357 * Figure out which of the changing fields changed. The
358 * receiver expects changes in the order: urgent, window,
359 * ack, seq (the order minimizes the number of temporaries
360 * needed in this section of code).
361 */
362 if(th->urg){
363 deltaS = ntohs(th->urg_ptr);
364 cp = encode(cp,deltaS);
365 changes |= NEW_U;
366 } else if(th->urg_ptr != oth->urg_ptr){
367 /* argh! URG not set but urp changed -- a sensible
368 * implementation should never do this but RFC793
369 * doesn't prohibit the change so we have to deal
370 * with it. */
371 goto uncompressed;
372 }
373 if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){
374 cp = encode(cp,deltaS);
375 changes |= NEW_W;
376 }
377 if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){
378 if(deltaA > 0x0000ffff)
379 goto uncompressed;
380 cp = encode(cp,deltaA);
381 changes |= NEW_A;
382 }
383 if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){
384 if(deltaS > 0x0000ffff)
385 goto uncompressed;
386 cp = encode(cp,deltaS);
387 changes |= NEW_S;
388 }
390 switch(changes){
391 case 0: /* Nothing changed. If this packet contains data and the
392 * last one didn't, this is probably a data packet following
393 * an ack (normal on an interactive connection) and we send
394 * it compressed. Otherwise it's probably a retransmit,
395 * retransmitted ack or window probe. Send it uncompressed
396 * in case the other side missed the compressed version.
397 */
398 if(ip->tot_len != cs->cs_ip.tot_len &&
399 ntohs(cs->cs_ip.tot_len) == hlen)
400 break;
401 goto uncompressed;
402 break;
403 case SPECIAL_I:
404 case SPECIAL_D:
405 /* actual changes match one of our special case encodings --
406 * send packet uncompressed.
407 */
408 goto uncompressed;
409 case NEW_S|NEW_A:
410 if(deltaS == deltaA &&
411 deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
412 /* special case for echoed terminal traffic */
413 changes = SPECIAL_I;
414 cp = new_seq;
415 }
416 break;
417 case NEW_S:
418 if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
419 /* special case for data xfer */
420 changes = SPECIAL_D;
421 cp = new_seq;
422 }
423 break;
424 }
425 deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
426 if(deltaS != 1){
427 cp = encode(cp,deltaS);
428 changes |= NEW_I;
429 }
430 if(th->psh)
431 changes |= TCP_PUSH_BIT;
432 /* Grab the cksum before we overwrite it below. Then update our
433 * state with this packet's header.
434 */
435 deltaA = ntohs(th->check);
436 memcpy(&cs->cs_ip,ip,20);
437 memcpy(&cs->cs_tcp,th,20);
438 /* We want to use the original packet as our compressed packet.
439 * (cp - new_seq) is the number of bytes we need for compressed
440 * sequence numbers. In addition we need one byte for the change
441 * mask, one for the connection id and two for the tcp checksum.
442 * So, (cp - new_seq) + 4 bytes of header are needed.
443 */
444 deltaS = cp - new_seq;
445 if(compress_cid == 0 || comp->xmit_current != cs->cs_this){
446 cp = ocp;
447 *cpp = ocp;
448 *cp++ = changes | NEW_C;
449 *cp++ = cs->cs_this;
450 comp->xmit_current = cs->cs_this;
451 } else {
452 cp = ocp;
453 *cpp = ocp;
454 *cp++ = changes;
455 }
456 cp = put16(cp,(short)deltaA); /* Write TCP checksum */
457 /* deltaS is now the size of the change section of the compressed header */
458 memcpy(cp,new_seq,deltaS); /* Write list of deltas */
459 memcpy(cp+deltaS,icp+hlen,isize-hlen);
460 comp->sls_o_compressed++;
461 ocp[0] |= SL_TYPE_COMPRESSED_TCP;
462 return isize - hlen + deltaS + (cp - ocp);
464 /* Update connection state cs & send uncompressed packet (i.e.,
465 * a regular ip/tcp packet but with the 'conversation id' we hope
466 * to use on future compressed packets in the protocol field).
467 */
468 uncompressed:
469 memcpy(&cs->cs_ip,ip,20);
470 memcpy(&cs->cs_tcp,th,20);
471 if (ip->ihl > 5)
472 memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
473 if (th->doff > 5)
474 memcpy(cs->cs_tcpopt, th+1, ((th->doff) - 5) * 4);
475 comp->xmit_current = cs->cs_this;
476 comp->sls_o_uncompressed++;
477 memcpy(ocp, icp, isize);
478 *cpp = ocp;
479 ocp[9] = cs->cs_this;
480 ocp[0] |= SL_TYPE_UNCOMPRESSED_TCP;
481 return isize;
482 }
485 int
486 slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
487 {
488 register int changes;
489 long x;
490 register struct tcphdr *thp;
491 register struct iphdr *ip;
492 register struct cstate *cs;
493 int len, hdrlen;
494 unsigned char *cp = icp;
496 /* We've got a compressed packet; read the change byte */
497 comp->sls_i_compressed++;
498 if(isize < 3){
499 comp->sls_i_error++;
500 return 0;
501 }
502 changes = *cp++;
503 if(changes & NEW_C){
504 /* Make sure the state index is in range, then grab the state.
505 * If we have a good state index, clear the 'discard' flag.
506 */
507 x = *cp++; /* Read conn index */
508 if(x < 0 || x > comp->rslot_limit)
509 goto bad;
511 comp->flags &=~ SLF_TOSS;
512 comp->recv_current = x;
513 } else {
514 /* this packet has an implicit state index. If we've
515 * had a line error since the last time we got an
516 * explicit state index, we have to toss the packet. */
517 if(comp->flags & SLF_TOSS){
518 comp->sls_i_tossed++;
519 return 0;
520 }
521 }
522 cs = &comp->rstate[comp->recv_current];
523 thp = &cs->cs_tcp;
524 ip = &cs->cs_ip;
526 if((x = pull16(&cp)) == -1) { /* Read the TCP checksum */
527 goto bad;
528 }
529 thp->check = htons(x);
531 thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
532 /*
533 * we can use the same number for the length of the saved header and
534 * the current one, because the packet wouldn't have been sent
535 * as compressed unless the options were the same as the previous one
536 */
538 hdrlen = ip->ihl * 4 + thp->doff * 4;
540 switch(changes & SPECIALS_MASK){
541 case SPECIAL_I: /* Echoed terminal traffic */
542 {
543 register short i;
544 i = ntohs(ip->tot_len) - hdrlen;
545 thp->ack_seq = htonl( ntohl(thp->ack_seq) + i);
546 thp->seq = htonl( ntohl(thp->seq) + i);
547 }
548 break;
550 case SPECIAL_D: /* Unidirectional data */
551 thp->seq = htonl( ntohl(thp->seq) +
552 ntohs(ip->tot_len) - hdrlen);
553 break;
555 default:
556 if(changes & NEW_U){
557 thp->urg = 1;
558 if((x = decode(&cp)) == -1) {
559 goto bad;
560 }
561 thp->urg_ptr = htons(x);
562 } else
563 thp->urg = 0;
564 if(changes & NEW_W){
565 if((x = decode(&cp)) == -1) {
566 goto bad;
567 }
568 thp->window = htons( ntohs(thp->window) + x);
569 }
570 if(changes & NEW_A){
571 if((x = decode(&cp)) == -1) {
572 goto bad;
573 }
574 thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
575 }
576 if(changes & NEW_S){
577 if((x = decode(&cp)) == -1) {
578 goto bad;
579 }
580 thp->seq = htonl( ntohl(thp->seq) + x);
581 }
582 break;
583 }
584 if(changes & NEW_I){
585 if((x = decode(&cp)) == -1) {
586 goto bad;
587 }
588 ip->id = htons (ntohs (ip->id) + x);
589 } else
590 ip->id = htons (ntohs (ip->id) + 1);
592 /*
593 * At this point, cp points to the first byte of data in the
594 * packet. Put the reconstructed TCP and IP headers back on the
595 * packet. Recalculate IP checksum (but not TCP checksum).
596 */
598 len = isize - (cp - icp);
599 if (len < 0)
600 goto bad;
601 len += hdrlen;
602 ip->tot_len = htons(len);
603 ip->check = 0;
605 memmove(icp + hdrlen, cp, len - hdrlen);
607 cp = icp;
608 memcpy(cp, ip, 20);
609 cp += 20;
611 if (ip->ihl > 5) {
612 memcpy(cp, cs->cs_ipopt, (ip->ihl - 5) * 4);
613 cp += (ip->ihl - 5) * 4;
614 }
616 put_unaligned(ip_fast_csum(icp, ip->ihl),
617 &((struct iphdr *)icp)->check);
619 memcpy(cp, thp, 20);
620 cp += 20;
622 if (thp->doff > 5) {
623 memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4);
624 cp += ((thp->doff) - 5) * 4;
625 }
627 return len;
628 bad:
629 comp->sls_i_error++;
630 return slhc_toss( comp );
631 }
634 int
635 slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
636 {
637 register struct cstate *cs;
638 unsigned ihl;
640 unsigned char index;
642 if(isize < 20) {
643 /* The packet is shorter than a legal IP header */
644 comp->sls_i_runt++;
645 return slhc_toss( comp );
646 }
647 /* Peek at the IP header's IHL field to find its length */
648 ihl = icp[0] & 0xf;
649 if(ihl < 20 / 4){
650 /* The IP header length field is too small */
651 comp->sls_i_runt++;
652 return slhc_toss( comp );
653 }
654 index = icp[9];
655 icp[9] = IPPROTO_TCP;
657 if (ip_fast_csum(icp, ihl)) {
658 /* Bad IP header checksum; discard */
659 comp->sls_i_badcheck++;
660 return slhc_toss( comp );
661 }
662 if(index > comp->rslot_limit) {
663 comp->sls_i_error++;
664 return slhc_toss(comp);
665 }
667 /* Update local state */
668 cs = &comp->rstate[comp->recv_current = index];
669 comp->flags &=~ SLF_TOSS;
670 memcpy(&cs->cs_ip,icp,20);
671 memcpy(&cs->cs_tcp,icp + ihl*4,20);
672 if (ihl > 5)
673 memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4);
674 if (cs->cs_tcp.doff > 5)
675 memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
676 cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
677 /* Put headers back on packet
678 * Neither header checksum is recalculated
679 */
680 comp->sls_i_uncompressed++;
681 return isize;
682 }
684 int
685 slhc_toss(struct slcompress *comp)
686 {
687 if ( comp == NULLSLCOMPR )
688 return 0;
690 comp->flags |= SLF_TOSS;
691 return 0;
692 }
695 /* VJ header compression */
696 EXPORT_SYMBOL(slhc_init);
697 EXPORT_SYMBOL(slhc_free);
698 EXPORT_SYMBOL(slhc_remember);
699 EXPORT_SYMBOL(slhc_compress);
700 EXPORT_SYMBOL(slhc_uncompress);
701 EXPORT_SYMBOL(slhc_toss);
703 #ifdef MODULE
705 int init_module(void)
706 {
707 printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California\n");
708 return 0;
709 }
711 void cleanup_module(void)
712 {
713 return;
714 }
716 #endif /* MODULE */
717 #else /* CONFIG_INET */
720 int
721 slhc_toss(struct slcompress *comp)
722 {
723 printk(KERN_DEBUG "Called IP function on non IP-system: slhc_toss");
724 return -EINVAL;
725 }
726 int
727 slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
728 {
729 printk(KERN_DEBUG "Called IP function on non IP-system: slhc_uncompress");
730 return -EINVAL;
731 }
732 int
733 slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
734 unsigned char *ocp, unsigned char **cpp, int compress_cid)
735 {
736 printk(KERN_DEBUG "Called IP function on non IP-system: slhc_compress");
737 return -EINVAL;
738 }
740 int
741 slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
742 {
743 printk(KERN_DEBUG "Called IP function on non IP-system: slhc_remember");
744 return -EINVAL;
745 }
747 void
748 slhc_free(struct slcompress *comp)
749 {
750 printk(KERN_DEBUG "Called IP function on non IP-system: slhc_free");
751 return;
752 }
753 struct slcompress *
754 slhc_init(int rslots, int tslots)
755 {
756 printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init");
757 return NULL;
758 }
759 EXPORT_SYMBOL(slhc_init);
760 EXPORT_SYMBOL(slhc_free);
761 EXPORT_SYMBOL(slhc_remember);
762 EXPORT_SYMBOL(slhc_compress);
763 EXPORT_SYMBOL(slhc_uncompress);
764 EXPORT_SYMBOL(slhc_toss);
766 #endif /* CONFIG_INET */
767 MODULE_LICENSE("Dual BSD/GPL");