ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/comp.c
Revision: 1.1
Committed: Sun Feb 8 06:02:44 2004 UTC (20 years, 4 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: ROHC-IMPORT-2004-02-08
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*
2     ROHC Project 2003 at Lulea University of Technology, Sweden.
3     Authors: Andreas Vernersson <andver-8@student.luth.se>
4     Daniel Pettersson <danpet-7@student.luth.se>
5     Erik Soderstrom <soderstrom@yahoo.com>
6     Fredrik Lindstrom <frelin-9@student.luth.se>
7     Johan Stenmark <johste-8@student.luth.se>
8     Martin Juhlin <juhlin@users.sourceforge.net>
9     Mikael Larsson <larmik-9@student.luth.se>
10     Robert Maxe <robmax-1@student.luth.se>
11    
12     Copyright (C) 2003 Andreas Vernersson, Daniel Pettersson,
13     Erik Soderström, Fredrik Lindström, Johan Stenmark,
14     Martin Juhlin, Mikael Larsson, Robert Maxe.
15    
16     This program is free software; you can redistribute it and/or modify
17     it under the terms of the GNU General Public License as published by
18     the Free Software Foundation; either version 2 of the License, or
19     (at your option) any later version.
20    
21     This program is distributed in the hope that it will be useful,
22     but WITHOUT ANY WARRANTY; without even the implied warranty of
23     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24     GNU General Public License for more details.
25    
26     You should have received a copy of the GNU General Public License
27     along with this program; if not, write to the Free Software
28     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29     */
30     /***************************************************************************
31     * File: comp.c *
32     * Description: description *
33     ***************************************************************************/
34    
35     #include "rohc.h"
36     #include "comp.h"
37     #include "c_util.h"
38    
39     #include "decomp.h"
40     #include "d_util.h"
41    
42     #include "proc_rohc.h"
43    
44     ///////////////////////////////////////////////////////////////////////
45     // Profile definitions and variables
46    
47     // Profile IDs
48     #define ROHC_PROFILE_UNCOMPRESSED 0
49     #define ROHC_PROFILE_UDP 2
50     #define ROHC_PROFILE_UDPLITE 8
51     #define ROHC_PROFILE_IP 4
52    
53     // The profiles.. in c_ip.c, c_udp.c, c_udp_lite.c, c_uncompressed.c
54     extern struct sc_profile c_ip_profile;
55     extern struct sc_profile c_uncompressed_profile;
56     extern struct sc_profile c_udp_profile;
57     extern struct sc_profile c_udp_lite_profile;
58    
59     /* C_NUM_PROFILES is defined in comp.h */
60    
61     // Pointers to all profiles:
62     static struct sc_profile *c_profiles[C_NUM_PROFILES] = {
63     &c_udp_profile,
64     &c_udp_lite_profile,
65     &c_ip_profile,
66     &c_uncompressed_profile
67     };
68    
69     ////////////////////////////////////////////////////////////////////////
70     // Feedback variables
71     static void c_piggyback_destroy(struct sc_rohc *);
72     static int c_piggyback_get(struct sc_rohc *, unsigned char *buf);
73    
74     ////////////////////////////////////////////////////////////////////////
75     // Context definitions functions
76     static void c_destroy_contexts(struct sc_rohc *);
77     static int c_create_contexts(struct sc_rohc *);
78     static int c_alloc_contexts(struct sc_rohc *, int num);
79    
80    
81     ////////////////////////////////////////////////////////////////////////
82     // Public functions
83    
84     /* Allocate space for a compressor (transmit side) */
85     void *rohc_alloc_compressor(int max_cid)
86     {
87    
88     struct sc_rohc *comp;
89     int i;
90     rohc_debugf(1, "ROHC: Allocating compressor\n");
91    
92     comp = kmalloc(sizeof(struct sc_rohc), GFP_ATOMIC);
93     if (comp == NULL) {
94     rohc_debugf(0, "rohc_alloc_compressor() no mem for compressor!\n");
95     return NULL;
96     }
97    
98     comp->enabled = 1;
99     comp->feedback_pointer = 0;
100     comp->max_cid = max_cid;
101     comp->large_cid = 0;
102     comp->mrru = 0;
103    
104     for (i = 0; i < C_NUM_PROFILES; i++) {
105     comp->profiles[i] = 0;
106     }
107    
108     comp->num_packets = 0;
109     comp->total_compressed_size = 0;
110     comp->total_uncompressed_size = 0;
111    
112     for (i=0; i<FEEDBACK_BUFFER_SIZE; i++) {
113     comp->feedback_buffer[i] = (void*)0;
114     comp->feedback_size[i] = 0;
115     }
116    
117     if (!c_create_contexts(comp)) {
118     return NULL;
119     }
120    
121     return comp;
122     }
123    
124    
125     /* Free space used by a compressor */
126     void rohc_free_compressor(struct sc_rohc *comp) {
127    
128     rohc_debugf(2,"ROHC: Free contexts\n");
129     // free memory used by contexts..
130     c_destroy_contexts(comp);
131    
132     rohc_debugf(2,"ROHC: Free piggybacks\n");
133     // destroy unsent piggybacked feedback
134     c_piggyback_destroy(comp);
135    
136     // free profile array
137     rohc_debugf(2,"ROHC: Free profiles\n");
138    
139     // free compressor..
140     kfree(comp);
141     }
142    
143    
144     /* Compress a packet */
145     int rohc_compress(struct sc_rohc *comp, unsigned char *ibuf, int isize,
146     unsigned char *obuf, int osize)
147     {
148     struct iphdr *ip = (struct iphdr *)(ibuf); // + PPP_HDRLEN);
149     int proto = ip->protocol;
150     struct sc_profile *p;
151     struct sc_context *c;
152     int feedback_size, payload_size, payload_offset;
153     int size, esize;
154    
155     if (comp == 0) {
156     rohc_debugf(0, "c_compress(): comp=null!\n");
157     return 0;
158     }
159    
160     if (ip->version != 4) {
161     rohc_debugf(0, "Wrong IP version (%d)\n", ip->version);
162     return 0;
163     }
164    
165     if (ip->ihl*4 != 20) {
166     rohc_debugf(0, "Wrong IP header size (%d)\n", ip->ihl);
167     return 0;
168     }
169    
170     // Get profile based on ip->protocol..
171     rohc_debugf(2,"c_compress(): protocoll %d \n", proto);
172     p = c_get_profile_from_protocol(comp, proto);
173    
174     if (p == 0) // use IP-profile if no profile was found based on the protocol
175     {
176     rohc_debugf(2,"c_compress(): Using IP profile\n");
177     p = c_get_profile_from_id(comp, ROHC_PROFILE_IP);
178    
179     if (p == 0) { // Use Uncompressed-profile if IP profile was not found..
180     rohc_debugf(0,"c_compress(): Using UNCOMPRESSED profile\n");
181     p = c_get_profile_from_id(comp, ROHC_PROFILE_UNCOMPRESSED);
182    
183     if (p == 0) {
184     rohc_debugf(0,"c_compress(): No profile found, giving up\n");
185     return 0;
186     }
187     }
188     }
189    
190    
191     // Get Context using help from the profiles..
192     c = c_find_context(comp, p, ip);
193    
194     if (c==0) // skapa nytt context
195     c = c_create_context(comp, p, ip);
196     else if (c==(struct sc_context*)-1) {
197     // the profile dedected anomalities in ip-packet (such as fragments) that made
198     // it un-compressible - switch to Uncompressed profile!
199    
200     p = c_get_profile_from_id(comp, ROHC_PROFILE_UNCOMPRESSED);
201     c = c_find_context(comp, p, ip); // find the uncompressed
202     if (c==0)
203     c = c_create_context(comp, p, ip);
204     }
205    
206    
207     c->latest_used = get_milliseconds();
208    
209     // copy PPP header
210     //memcpy(obuf, rptr, PPP_HDRLEN);
211     // change protocol in ppp header to rohc-over-ppp identifier???
212     size = 0; //PPP_HDRLEN;
213    
214     // add feedback
215     feedback_size = c_piggyback_get(comp, obuf);
216     obuf += feedback_size;
217     size += feedback_size;
218    
219     // use profile to compress packet
220     esize = p->encode(c, ip, isize, obuf, osize - size, &payload_offset);
221    
222     if (esize < 0) { // error while compressing.. use uncompressed..
223     if (c->num_send_packets <= 1) { // free context
224     c->profile->destroy(c);
225     c->used = 0;
226     }
227    
228     p = c_get_profile_from_id(comp, ROHC_PROFILE_UNCOMPRESSED);
229     c = c_find_context(comp, p, ip); // find the uncompressed
230     if (c==0)
231     c = c_create_context(comp, p, ip);
232    
233     if (c!=0)
234     esize = p->encode(c, ip, isize, obuf, osize - size, &payload_offset);
235     else {
236     rohc_debugf(0, "c_compress(): Failed to create uncompressed context!\n");
237     return 0;
238     }
239     }
240    
241     size += esize;
242     obuf += esize;
243    
244     payload_size = ntohs(ip->tot_len) - payload_offset;
245    
246     rohc_debugf(2,"c_compress(): ROHC size=%d, Payload size=%d (totlen=%d, ihl=%d), outbut buffer size=%d\n", size, payload_size, ntohs(ip->tot_len), ip->ihl*4, osize);
247    
248     if (size + payload_size > osize) // packet to big!!!
249     {
250     // do uncompressed!!
251     rohc_debugf(0,"ROHC packet to large (osize=%d, isize=%d)\n", size+payload_size, isize);
252     return 0;
253     }
254    
255     // copy payload to rohc packet..
256     memcpy(obuf, ((unsigned char*)ip) + payload_offset, payload_size);
257    
258     obuf += payload_size;
259     size += payload_size;
260    
261     // Update statistic..
262     comp->num_packets ++;
263     comp->total_uncompressed_size += isize;
264     comp->total_compressed_size += size;
265    
266     c->total_uncompressed_size += isize;
267     c->total_compressed_size += size;
268     c->header_uncompressed_size += payload_offset;
269     c->header_compressed_size += esize;
270     c->num_send_packets ++;
271     c_add_wlsb(c->total_16_uncompressed, 0, 0, isize);
272     c_add_wlsb(c->total_16_compressed, 0,0, size);
273     c_add_wlsb(c->header_16_uncompressed, 0, 0, payload_offset);
274     c_add_wlsb(c->header_16_compressed, 0,0, esize);
275    
276     return size;
277     }
278    
279     // Used in the handshake to active profiles that are can be used
280     void rohc_activate_profile(struct sc_rohc * comp, int profile)
281     {
282     int i;
283     for (i = 0; i < C_NUM_PROFILES; i++) {
284     if (c_profiles[i]->id == profile) {
285     comp->profiles[i] = 1;
286     return;
287     }
288     }
289     rohc_debugf(0, "Unknown ROHC profile with id = %d\n", profile);
290     }
291    
292     int rohc_c_using_small_cid(struct sc_rohc * comp)
293     {
294     return !comp->large_cid;
295     }
296    
297     void rohc_c_set_header(struct sc_rohc *compressor, int header)
298     {
299     compressor->max_header_size = header;
300     }
301    
302     void rohc_c_set_mrru(struct sc_rohc *compressor, int value) {
303     compressor->mrru = value;
304     }
305    
306     void rohc_c_set_max_cid(struct sc_rohc *compressor, int value) {
307     if (compressor->large_cid) {
308     if (value > 0 && value < 65536)
309     compressor->max_cid = value;
310     } else {
311     if (value > 0 && value < 16)
312     compressor->max_cid = value;
313     }
314     }
315    
316     void rohc_c_set_large_cid(struct sc_rohc *compressor, int value) {
317     if (value) {
318     compressor->large_cid = 1;
319     } else {
320     compressor->large_cid = 0;
321     if (compressor->max_cid > 15)
322     compressor->max_cid = 15;
323     }
324     }
325    
326     void rohc_c_set_connection_type(struct sc_rohc *compressor, int value) {
327     compressor->connection_type = value;
328     }
329    
330     void rohc_c_set_enable(struct sc_rohc *compressor, int value) {
331     compressor->enabled = value;
332     }
333    
334     int rohc_c_is_enabled(struct sc_rohc *compressor) {
335     return compressor->enabled;
336     }
337    
338    
339     /* Called by proc_rohc to get information about available profiles (used in usermode ppp for handshake)*/
340     int rohc_c_info(char *buffer) {
341     int i;
342    
343     sprintf(buffer, "%s\n", "---Information");
344    
345     //"Profiles: 1 2 3 4"
346     sprintf(buffer, "%s%s", buffer, "Profiles:");
347     for (i=0; i<C_NUM_PROFILES; i++) {
348     sprintf(buffer, "%s%d ", buffer, c_profiles[i]->id);
349     }
350     sprintf(buffer, "%s\n", buffer);
351    
352     return strlen(buffer);
353     }
354    
355     /* Called by proc_rohc to get information about the compressor */
356     int rohc_c_statistics(struct sc_rohc *comp, char *buffer)
357     {
358     char *save;
359     struct sc_profile *p;
360     int i,v;
361    
362     save = buffer;
363    
364     // Instance part..
365     buffer += strlen(buffer);
366     sprintf(buffer, "\n---Instance\n");
367     buffer += strlen(buffer);
368     sprintf(buffer, "CREATOR:%s\n", "LULEA/SMD143/2003");
369     buffer += strlen(buffer);
370     sprintf(buffer, "VERSION NO:%s\n", "1.0");
371     buffer += strlen(buffer);
372     sprintf(buffer, "STATUS:%s\n", comp->enabled?"ENABLED":"DISABLED");
373     buffer += strlen(buffer);
374     sprintf(buffer, "NO COMPRESSED FLOWS:%d\n", comp->num_used);
375     buffer += strlen(buffer);
376     sprintf(buffer, "TOTAL NO PACKETS:%d\n", comp->num_packets);
377     buffer += strlen(buffer);
378    
379     if (comp->total_uncompressed_size != 0)
380     v = (100 * comp->total_compressed_size) / comp->total_uncompressed_size;
381     else
382     v = 0;
383     sprintf(buffer, "TOTAL COMPRESSION RATIO:%d%%\n", v);
384     buffer += strlen(buffer);
385     sprintf(buffer, "MAX_CID:%d\n", comp->max_cid);
386     buffer += strlen(buffer);
387     sprintf(buffer, "MRRU:%d\n", 4); // comp->mrru
388     buffer += strlen(buffer);
389     sprintf(buffer, "LARGE_CID:%s\n", comp->large_cid?"YES" : "NO");
390     buffer += strlen(buffer);
391     sprintf(buffer, "CONNECTION_TYPE:%d\n", 3);
392     buffer += strlen(buffer);
393     sprintf(buffer, "FEEDBACK_FREQ:%d\n", 7); // comp-> ??
394     buffer += strlen(buffer);
395    
396     // profiles part
397     for (i=0; i<C_NUM_PROFILES; i++) {
398     p = c_profiles[i];
399    
400     sprintf(buffer, "\n---Profile\n");
401     buffer += strlen(buffer);
402     sprintf(buffer, "PROFILE NO:%d\n", p->id);
403     buffer += strlen(buffer);
404     sprintf(buffer, "ACTIVE:%s\n", comp->profiles[i]?"YES":"NO");
405     buffer += strlen(buffer);
406     sprintf(buffer, "VERSION NO:%s\n", p->version);
407     buffer += strlen(buffer);
408     sprintf(buffer, "PROFILE TYPE:%s\n", p->description);
409     buffer += strlen(buffer);
410     }
411    
412     return strlen(save);
413     }
414    
415     /* Called by proc_rohc to get information about a context (cid=index)
416     * Returns -2 if index is larger than allocated cids
417     * Returns -1 if cid is unused
418     * Else returns length if buffer..
419     */
420     int rohc_c_context(struct sc_rohc *comp, int index, char *buffer) {
421     struct sc_context *c;
422     char *save;
423     char *modes[4]= {"error", "U-mode", "O-mode", "R-mode"};
424     char *states[4] = {"error", "IR", "FO", "SO"};
425     int v;
426    
427     // Compressor Contexts
428     if (index >= comp->num_allocated)
429     return -2;
430    
431     c = &comp->contexts[index];
432     if (!c->used)
433     return -1;
434    
435     save = buffer;
436     buffer += strlen(buffer);
437     sprintf(buffer, "\n%s\n", "---Context");
438     buffer += strlen(buffer);
439     sprintf(buffer, "CONTEXTTYPE:Compressor\n");
440     buffer += strlen(buffer);
441     sprintf(buffer, "CID:%d\n", c->cid);
442     buffer += strlen(buffer);
443     sprintf(buffer, "CID_STATE:%s\n", c->used?"USED":"UNUSED");
444     buffer += strlen(buffer);
445     sprintf(buffer, "STATE:%s\n", states[c->c_state]);
446     buffer += strlen(buffer);
447     sprintf(buffer, "MODE:%s\n", modes[c->c_mode]);
448     buffer += strlen(buffer);
449     sprintf(buffer, "PROFILE:%s\n", c->profile->description);
450     buffer += strlen(buffer);
451    
452     if (c->total_uncompressed_size != 0)
453     v = (100*c->total_compressed_size) / c->total_uncompressed_size;
454     else
455     v = 0;
456     if (v < 0) {
457     rohc_debugf(0, "comp: total_compressed_size=%d total_uncompressed_size=%d\n", c->total_compressed_size, c->total_uncompressed_size);
458     }
459     sprintf(buffer, "TOTALCOMPRATIOALLPACK:%d%%\n", v);
460     buffer += strlen(buffer);
461    
462     if (c->header_uncompressed_size != 0)
463     v = (100*c->header_compressed_size) / c->header_uncompressed_size;
464     else
465     v = 0;
466     sprintf(buffer, "TOTALCOMPRATIOALLPACKHEAD:%d%%\n", v);
467     buffer += strlen(buffer);
468    
469     if (c->num_send_packets != 0)
470     v = c->total_compressed_size / c->num_send_packets;
471     else
472     v = 0;
473     sprintf(buffer, "MEANCOMPPACKSIZEALLPACK:%d\n", v);
474     buffer += strlen(buffer);
475    
476     if (c->num_send_packets != 0)
477     v = c->header_compressed_size / c->num_send_packets;
478     else
479     v = 0;
480     sprintf(buffer, "MEANHEADSIZEALLCOMPHEAD:%d\n", v);
481     buffer += strlen(buffer);
482    
483     v = c_sum_wlsb(c->total_16_uncompressed);
484     if (v != 0)
485     v = (100*c_sum_wlsb(c->total_16_compressed)) / v;
486     sprintf(buffer, "COMPRATIOLAST16PACK:%d%%\n", v);
487     buffer += strlen(buffer);
488    
489     v = c_sum_wlsb(c->header_16_uncompressed);
490     if (v != 0)
491     v = (100*c_sum_wlsb(c->header_16_compressed)) / v;
492     sprintf(buffer, "COMPRATIOLAST16PACKHEAD:%d%%\n", v);
493     buffer += strlen(buffer);
494    
495     v = c_mean_wlsb(c->total_16_compressed);
496     sprintf(buffer, "MEANCOMPPACKSIZELAST16PACK:%d\n", v);
497     buffer += strlen(buffer);
498    
499     v = c_mean_wlsb(c->header_16_compressed);
500     sprintf(buffer, "MEANHEADSIZELAST16COMPHEAD:%d\n", v);
501     buffer += strlen(buffer);
502     sprintf(buffer, "CONTEXTACTIVATIONTIME:%d\n", (get_milliseconds() - c->first_used)/1000);
503     buffer += strlen(buffer);
504     sprintf(buffer, "CONTEXTIDLETIME:%d\n", (get_milliseconds() - c->latest_used)/1000);
505     buffer += strlen(buffer);
506     sprintf(buffer, "NOSENTPACKETS:%d\n", c->num_send_packets);
507     buffer += strlen(buffer);
508     sprintf(buffer, "NOSENTIRPACKETS:%d\n", c->num_send_ir);
509     buffer += strlen(buffer);
510     sprintf(buffer, "NOSENTIRDYNPACKETS:%d\n", c->num_send_ir_dyn);
511     buffer += strlen(buffer);
512     sprintf(buffer, "NORECVFEEDBACKS:%d\n", c->num_recv_feedbacks);
513    
514     return strlen(save);
515     }
516    
517    
518     ////////////////////////////////////////////////////////////////////////
519     // Generic profile functions
520    
521     // Retrieve a profile given a profile_id
522     struct sc_profile *c_get_profile_from_id(struct sc_rohc *comp, int profile_id)
523     {
524     int i;
525     for (i=0; i<C_NUM_PROFILES; i++)
526     {
527     if (c_profiles[i]->id == profile_id && comp->profiles[i]==1)
528     return c_profiles[i];
529     }
530    
531     // log this failure maybe..
532     return NULL;
533     }
534    
535     // Retrieve a profile given a (ip) protocol id
536     struct sc_profile *c_get_profile_from_protocol(struct sc_rohc *comp, int protocol)
537     {
538     int i;
539     for (i=0; i<C_NUM_PROFILES; i++)
540     {
541     if (c_profiles[i]->protocol == protocol && comp->profiles[i]==1)
542     return c_profiles[i];
543     }
544    
545     return NULL;
546     }
547    
548     ////////////////////////////////////////////////////////////////////////
549     // Generic context functions
550    
551    
552     // Allocate the context array
553     static int c_alloc_contexts(struct sc_rohc *comp, int num) {
554     if (num > comp->max_cid+1)
555     num = comp->max_cid+1;
556    
557     if (comp->num_allocated < num) {
558     struct sc_context *tmp;
559     int i;
560    
561     tmp = kmalloc(sizeof(struct sc_context) * num, GFP_ATOMIC);
562     if (tmp == 0) {
563     rohc_debugf(0,"rohc_alloc_compressor() no mem for contexts!\n");
564     return 0;
565     }
566    
567     for (i=0; i<num; i++) {
568     tmp[i].used = 0;
569     }
570    
571     if (comp->num_allocated > 0 && comp->contexts) {
572     memcpy(tmp,comp->contexts, comp->num_allocated * sizeof(struct sc_context));
573     kfree(comp->contexts);
574     }
575    
576     for (i=comp->num_allocated; i<num; i++) {
577     tmp[i].total_16_uncompressed = c_create_wlsb(32, 16, 0); // create a window with 16 entries..
578     tmp[i].total_16_compressed = c_create_wlsb(32, 16, 0);
579     tmp[i].header_16_uncompressed = c_create_wlsb(32, 16, 0);
580     tmp[i].header_16_compressed = c_create_wlsb(32, 16, 0);
581     }
582    
583     comp->contexts = tmp;
584     comp->num_allocated = num;
585     }
586    
587     return 1;
588     }
589    
590     // Skapa en ny context
591     struct sc_context *c_create_context(struct sc_rohc *comp, struct sc_profile *profile, struct iphdr *ip) {
592     struct sc_context *c;
593     int index, i;
594    
595     index = 0;
596    
597     if (comp->num_used >= comp->max_cid+1) {
598     // find oldest or one not in use:
599     int minimum;
600    
601     find_oldest:
602    
603     index = 0;
604     minimum = 0x7fffffff;
605     for (i=0; i<comp->num_allocated; i++) {
606     if (comp->contexts[i].used == 0) {
607     index = i;
608     break;
609     } else if (comp->contexts[i].latest_used < minimum) {
610     minimum = comp->contexts[i].latest_used;
611     index = i;
612     }
613     }
614    
615     if (comp->contexts[index].used) {
616     // free memory..
617     rohc_debugf(2,"Freeing memory for recycled context (cid=%d)\n", index);
618     comp->contexts[index].profile->destroy(&comp->contexts[index]);
619     }
620    
621     } else if (comp->num_used >= comp->num_allocated) {
622     if (!c_alloc_contexts(comp, comp->num_used * 2))
623     goto find_oldest;
624    
625     index = comp->num_used;
626     comp->num_used ++;
627    
628     } else{
629     index = -1;
630     for (i=0; i<comp->num_used; i++) {
631     if (comp->contexts[i].used==0) {
632     index = i;
633     break;
634     }
635     }
636    
637     if (index==-1) {
638     index = comp->num_used;
639     comp->num_used++;
640     }
641     }
642    
643    
644     c = &comp->contexts[index];
645    
646     c->used = 1;
647     c->first_used = get_milliseconds();
648     c->latest_used = get_milliseconds();
649    
650     c->total_uncompressed_size = 0;
651     c->total_compressed_size = 0;
652     c->header_uncompressed_size = 0;
653     c->header_compressed_size = 0;
654     c->num_send_packets = 0;
655     c->num_send_ir = 0;
656     c->num_send_ir_dyn = 0;
657     c->num_recv_feedbacks = 0;
658    
659     c->cid = index;
660    
661     c->profile = profile;
662     c->profile_id = profile->id;
663    
664     c->c_mode = U;
665     c->c_state = IR;
666    
667     c->nbo = 1;
668     c->rnd = 0;
669    
670     c->nbo2 = 1;
671     c->rnd2 = 0;
672    
673     c->compressor = comp;
674     c->latest_used = get_milliseconds();
675    
676     rohc_debugf(1, "Creating context CID=%d (numUsed=%d)\n", c->cid, comp->num_used);
677    
678     // Create profile specific context and initialize..
679     if (profile->create(c, ip) == 0) {
680     c->used = 0;
681     return NULL;
682     }
683    
684     return c;
685     }
686    
687    
688    
689     // Find context given a profile and a ip packet..
690     struct sc_context *c_find_context(struct sc_rohc *comp, struct sc_profile *profile, struct iphdr *ip) {
691     int i;
692     int ret;
693     struct sc_context *c;
694    
695     rohc_debugf(2,"c_find_context(): %d\n", comp->num_used);
696    
697     for (i=0; i<comp->num_used; i++) {
698     c = &comp->contexts[i];
699    
700     if (c && !c->used) {
701     rohc_debugf(1,"Using unused context CID=%d\n", c->cid);
702     return c;
703     }
704     if (c && c->used && c->profile_id==profile->id) {
705     ret = c->profile->check_context(c, ip);
706    
707     if (ret==-1)
708     return (struct sc_context*)-1;
709     if (ret) {
710     rohc_debugf(1,"Using context CID=%d\n", c->cid);
711     return c;
712     }
713     }
714     }
715    
716     rohc_debugf(2,"c_find_context(): No context was found\n");
717     return NULL; // no matching context was found..
718     }
719    
720    
721     // Get context, given the CID
722     struct sc_context *c_get_context(struct sc_rohc *comp, int cid) {
723     if (cid > comp->num_allocated)
724     return NULL;
725     if (cid > comp->num_used)
726     return NULL;
727     if (comp->contexts[cid].used == 0)
728     return NULL;
729    
730     return &comp->contexts[cid];
731     }
732    
733    
734     // Allocate context memory..
735     static int c_create_contexts(struct sc_rohc *comp) {
736     comp->num_used = 0;
737     comp->num_allocated = 0;
738     comp->contexts = 0;
739    
740     return c_alloc_contexts(comp, 4); // start with 4 contexts from the beginning..
741     }
742    
743    
744     // Deallocate all contexts including their profile specific context
745     static void c_destroy_contexts(struct sc_rohc *comp) {
746     if (comp->num_allocated > 0) {
747     int i;
748     for (i=0; i<comp->num_allocated; i++) {
749    
750     if (comp->contexts[i].used && comp->contexts[i].profile != 0)
751     comp->contexts[i].profile->destroy(&comp->contexts[i]);
752    
753     c_destroy_wlsb(comp->contexts[i].total_16_uncompressed);
754     c_destroy_wlsb(comp->contexts[i].total_16_compressed);
755     c_destroy_wlsb(comp->contexts[i].header_16_uncompressed);
756     c_destroy_wlsb(comp->contexts[i].header_16_compressed);
757    
758     comp->contexts[i].used = 0;
759    
760     }
761    
762     kfree(comp->contexts);
763     }
764     }
765    
766    
767    
768     ////////////////////////////////////////////////////////////////////////
769     // Feedback functions for piggybacking
770    
771     // Add this feedback to the next outgoing ROHC packet:
772     void c_piggyback_feedback(struct sc_rohc *comp, unsigned char *feedback, int size) {
773     if (comp->feedback_pointer >= FEEDBACK_BUFFER_SIZE) // log this failure maybe?
774     return;
775    
776     comp->feedback_buffer[comp->feedback_pointer] = kmalloc(size, GFP_ATOMIC);
777     if (comp->feedback_buffer[comp->feedback_pointer] == 0) {
778     rohc_debugf(0,"c_piggyback_feedback() no mem for feedback!\n");
779     return;
780     }
781     memcpy(comp->feedback_buffer[comp->feedback_pointer], feedback, size);
782     comp->feedback_size[comp->feedback_pointer] = size;
783    
784     comp->feedback_pointer++;
785     }
786    
787     // Retrieve one feedback and store in buf. Return length of feedback
788     static int c_piggyback_get(struct sc_rohc *comp, unsigned char *buf) {
789     if (comp->feedback_pointer > 0) {
790     int size;
791     int index=0;
792    
793     comp->feedback_pointer--;
794     size = comp->feedback_size[comp->feedback_pointer];
795     if (size < 8) {
796     buf[index] = 0xf0 | size;
797     index++;
798     } else {
799     buf[index] = 0xf0;
800     index++;
801     buf[index] = size;
802     index++;
803     }
804    
805     memcpy(buf+index, comp->feedback_buffer[comp->feedback_pointer], size);
806    
807     kfree(comp->feedback_buffer[comp->feedback_pointer]);
808     comp->feedback_size[comp->feedback_pointer] = 0;
809    
810     return index + size;
811     }
812    
813     // No feedback exists..
814     return 0;
815     }
816    
817     // Destory memory allocated by the feedback buffer
818     static void c_piggyback_destroy(struct sc_rohc *comp) {
819     int i;
820    
821     for (i=0; i<FEEDBACK_BUFFER_SIZE; i++) {
822     if (comp->feedback_size[i] > 0 && comp->feedback_buffer[i] != 0)
823     kfree(comp->feedback_buffer[i]);
824     }
825     }
826    
827     ////////////////////////////////////////////////////////////////////////
828     // Feedback functions delivery to right profile/context..
829    
830    
831     // When feedback is received by the decompressor, this function is called
832     // and delivers that to the right profile/context..
833     void c_deliver_feedback(struct sc_rohc *comp, unsigned char *packet, int size) {
834     struct sc_context *c;
835     struct sc_feedback feedback;
836     unsigned char *p = packet;
837    
838     feedback.size = size;
839    
840     if (comp->large_cid) { // decode large cid.at p[0..3]
841     feedback.cid = d_sdvalue_decode(p);
842     p += d_sdvalue_size(p);
843     } else {
844     if (d_is_add_cid(p)) {
845     feedback.cid = d_decode_add_cid(p);
846     p++;
847     } else
848     feedback.cid = 0;
849     }
850    
851     feedback.specific_size = size - (p - packet);
852     rohc_debugf(2,"feedback size = %d\n",feedback.specific_size);
853     if (feedback.specific_size == 1)
854     feedback.type = 1; // FEEDBACK-1
855     else {
856     feedback.type = 2; // FEEDBACK-2
857     feedback.acktype = p[0]>>6;
858     }
859    
860     feedback.specific_offset = (p - packet);
861     feedback.data = kmalloc(feedback.size, GFP_ATOMIC);
862    
863     if (feedback.data == 0) {
864     rohc_debugf(0, "c_deliver_feedback(): no mem for feedback data\n");
865     return;
866     }
867    
868     rohc_debugf(2, "spec size %d\n",feedback.specific_size);
869    
870     memcpy(feedback.data,packet,feedback.size );
871    
872     // find cid.. get context
873     c = c_get_context(comp,feedback.cid);
874     if (c==0){
875     // Error: Context was not found..
876     rohc_debugf(0, "c_deliver_feedback(): Context not found (cid=%d)\n", feedback.cid);
877     kfree(feedback.data);
878     return;
879     }
880    
881     c->num_recv_feedbacks++;
882    
883     // deliver feedback to profile with the context..
884     c->profile->feedback(c, &feedback);
885    
886     kfree(feedback.data);
887    
888     }
889    
890    
891