ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/decomp.c
Revision: 1.3
Committed: Tue Apr 26 00:55:56 2005 UTC (19 years, 2 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_01, rel-3_0, rel-2_2, rel-2_0, rel-2_21, rel-2_22, rel-2_25, HEAD
Changes since 1.2: +1 -1 lines
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 pcg 1.3 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 pcg 1.1 */
30     //----------------------------------------------------------------------------------------------------------------------------------
31     #include "decomp.h"
32     #include "d_ip.h"
33     #include "d_udp.h"
34     #include "d_uncompressed.h"
35     #include "d_udp_lite.h"
36     #include "feedback.h"
37 pcg 1.2
38     #include "c_util.h"
39    
40 pcg 1.1 //----------------------------------------------------------------------------------------------------------------------------------
41     extern struct s_profile d_udplite_profile, d_udp_profile, d_ip_profile, d_uncomp_profile;
42     //----------------------------------------------------------------------------------------------------------------------------------
43     static struct s_profile *d_profiles[D_NUM_PROFILES] = {
44     &d_udplite_profile,
45     &d_udp_profile,
46     &d_ip_profile,
47     &d_uncomp_profile
48     };
49     //----------------------------------------------------------------------------------------------------------------------------------
50     static struct s_profile * find_profile(int id);
51     //----------------------------------------------------------------------------------------------------------------------------------
52     // Increases the context array size in sizes of 2^x (max 16384)
53     // Param state: pointer to decompressor
54     // Param highest cid: cid to adapt context array size with
55     //----------------------------------------------------------------------------------------------------------------------------------
56     void context_array_increase(struct sd_rohc * state, int highestcid)
57     {
58     struct sd_context ** pnew;
59     int calcsize, i;
60    
61     for(i=4; i<15; i++) { // calculate new size of array
62     calcsize = 1<<i;
63     if(highestcid < calcsize)
64     break;
65     }
66     pnew = (struct sd_context**)kmalloc(sizeof(struct sd_context*) * calcsize, GFP_ATOMIC); // allocate new array
67     if(!pnew) {
68     rohc_debugf(0,"[ERROR] context_array_increase(): unable to allocate memory!\n");
69     return;
70     }
71     for(i=0; i<calcsize; i++) // reset all new pointers to NULL
72     pnew[i] = NULL;
73     for(i=0; i<state->context_array_size; i++) // copy all pointers
74     pnew[i] = state->context[i];
75     state->context_array_size = calcsize;
76     kfree(state->context);
77     state->context = pnew;
78     }
79     //----------------------------------------------------------------------------------------------------------------------------------
80     // Decreases the context array size in sizes of 2^x (min 16)
81     // Param state: pointer to decompressor
82     //----------------------------------------------------------------------------------------------------------------------------------
83     void context_array_decrease(struct sd_rohc * state)
84     {
85     struct sd_context ** pnew;
86     int highestcid=0, calcsize, i;
87    
88     for(i=state->context_array_size-1; i>=0; i--) // search for the highest cid (from the end and backwards)
89     if(state->context[i]) {
90     highestcid = i;
91     break;
92     }
93     for(i=4; i<15; i++) { // calculate new size of array
94     calcsize = 1<<i;
95     if(highestcid < calcsize)
96     break;
97     }
98     pnew = (struct sd_context **)kmalloc(sizeof(struct sd_context*) * calcsize, GFP_ATOMIC); // allocate new array
99     if(!pnew) {
100     rohc_debugf(0,"[ERROR] context_array_decrease(): unable to allocate memory!\n");
101     return;
102     }
103     for(i=0; i<calcsize; i++) // reset all new pointers to NULL
104     pnew[i] = NULL;
105     for(i=0; i<=highestcid; i++) // copy all pointers
106     pnew[i] = state->context[i];
107    
108     state->context_array_size = calcsize;
109     kfree(state->context);
110     state->context = pnew;
111     }
112     //----------------------------------------------------------------------------------------------------------------------------------
113     // Finds a specific context
114     // Param state: pointer to decompressor
115     // Param cid: context-id to find in array
116     // Return: pointer to context if found, else NULL
117     //----------------------------------------------------------------------------------------------------------------------------------
118     struct sd_context * find_context(struct sd_rohc * state, int cid)
119     {
120     if(cid < state->context_array_size) // cid must not be equal or larger than the context array size
121     return(state->context[cid]);
122    
123     return(NULL);
124     }
125     //----------------------------------------------------------------------------------------------------------------------------------
126     // Create and allocate a new context with profile specific data
127     // Param state: pointer to decompressor
128     // Param with_cid: context-id (not used for now)
129     // Param profile: profile to be assigned with context
130     // Return: pointer to new context if allocatable, else NULL
131     //----------------------------------------------------------------------------------------------------------------------------------
132     struct sd_context * context_create(struct sd_rohc * state, int with_cid, struct s_profile * profile)
133     {
134     struct sd_context * pnew = (struct sd_context*)kmalloc(sizeof(struct sd_context), GFP_ATOMIC);
135     if(!pnew) {
136     rohc_debugf(0,"[ERROR] context_create(): unable to allocate memory!\n");
137     return(NULL);
138     }
139     pnew->profile = profile;
140     pnew->mode = ROHC_U_MODE;
141     pnew->state = ROHC_NO_CONTEXT;
142     pnew->data = profile->allocate_decode_data();
143     if(!pnew->data) {
144     kfree(pnew);
145     return(NULL);
146     }
147     pnew->curval = 0;
148    
149     pnew->num_recv_packets = 0;
150     pnew->total_uncompressed_size = 0;
151     pnew->total_compressed_size = 0;
152     pnew->header_uncompressed_size = 0;
153     pnew->header_compressed_size = 0;
154     pnew->num_recv_ir = 0;
155     pnew->num_recv_ir_dyn = 0;
156     pnew->num_sent_feedbacks = 0;
157     pnew->num_decomp_failures = 0;
158     pnew->num_decomp_repairs = 0;
159    
160     pnew->first_used = get_milliseconds();
161     pnew->latest_used = get_milliseconds();
162    
163     pnew->total_16_uncompressed = c_create_wlsb(32, 16, 0); // create a window with 16 entries..
164     pnew->total_16_compressed = c_create_wlsb(32, 16, 0);
165     pnew->header_16_uncompressed = c_create_wlsb(32, 16, 0);
166     pnew->header_16_compressed = c_create_wlsb(32, 16, 0);
167    
168     return(pnew);
169     }
170     //----------------------------------------------------------------------------------------------------------------------------------
171     // Free a context and the profile specific data within
172     // Param context: context to free
173     //----------------------------------------------------------------------------------------------------------------------------------
174     void context_free(struct sd_context * context)
175     {
176     if(!context)
177     return;
178    
179     context->profile->free_decode_data(context->data);
180    
181     c_destroy_wlsb(context->total_16_uncompressed);
182     c_destroy_wlsb(context->total_16_compressed);
183     c_destroy_wlsb(context->header_16_uncompressed);
184     c_destroy_wlsb(context->header_16_compressed);
185    
186     kfree(context);
187     }
188     //----------------------------------------------------------------------------------------------------------------------------------
189     // Create and allocate a ROHC-decompressor
190     // Param compressor: pointer to ROHC-compressor
191     // Return: pointer to the newly allocated decompressor
192     //----------------------------------------------------------------------------------------------------------------------------------
193     struct sd_rohc * rohc_alloc_decompressor(struct sc_rohc * compressor)
194     {
195     struct s_medium medium = {ROHC_SMALL_CID, 15 }; //, 3};
196     struct sd_rohc * pnew = (struct sd_rohc *)kmalloc(sizeof(struct sd_rohc), GFP_ATOMIC);
197     if(!pnew) {
198     rohc_debugf(0,"[ERROR] rohc_alloc_decompressor(): unable to allocate memory!\n");
199     return(NULL);
200     }
201     pnew->medium = (struct s_medium*)kmalloc(sizeof(struct s_medium), GFP_ATOMIC);
202     if (!pnew->medium) {
203     rohc_debugf(0,"[ERROR] rohc_alloc_decompressor(): unable to allocate memory (2)!\n");
204     kfree(pnew);
205     return(NULL);
206     }
207     memcpy(pnew->medium, &medium, sizeof(struct s_medium));
208    
209     pnew->compressor = compressor;
210    
211     pnew->context_array_size = 0; // must be zero
212     pnew->context = NULL; // must be NULL
213     context_array_increase(pnew, 0); // initialize array of size 16
214    
215     pnew->maxval = 300;
216     pnew->errval = 100;
217     pnew->okval = 12;
218     pnew->curval = 0;
219    
220     clear_statistics(pnew);
221    
222     return(pnew);
223     }
224     //----------------------------------------------------------------------------------------------------------------------------------
225     // Free and deallocate a ROHC-decompressor
226     // Param state: pointer to the ROHC-decompressor to free
227     //----------------------------------------------------------------------------------------------------------------------------------
228     void rohc_free_decompressor(struct sd_rohc * state)
229     {
230     int i;
231    
232     for(i=0; i<state->context_array_size; i++)
233     if(state->context[i])
234     context_free(state->context[i]);
235     kfree(state->context);
236     kfree(state->medium);
237     kfree(state);
238     }
239     //----------------------------------------------------------------------------------------------------------------------------------
240     // Main function for decompressing a ROHC-packet
241     // Param state: pointer to decompressor
242     // Param ibuf: pointer to incoming packet
243     // Param isize: size of incoming packet
244     // Param obuf: pointer to output buffer
245     // Param osize: size of output buffer
246     // Return: size of decompressed packet
247     //TODO: kolla upp s�ingen annan anropar d_decode_header DIREKT, anropen m�te ske till denna funktion, annars funkar inte statistik och feedback!!
248     //----------------------------------------------------------------------------------------------------------------------------------
249     int rohc_decompress(struct sd_rohc * state, unsigned char * ibuf, int isize, unsigned char * obuf, int osize)
250     {
251     int ret;
252     struct sd_decode_data ddata = { -1, 0, 0, NULL }; // { cid, addcidUsed, largecidUsed, sd_context * active }
253    
254     state->statistics.packets_received++;
255     ret = d_decode_header(state, ibuf, isize, obuf, osize, &ddata);
256     if(ddata.active == NULL && (ret == ROHC_ERROR_PACKAGE_FAILED || ret == ROHC_ERROR || ret == ROHC_ERROR_CRC))
257     ret = ROHC_ERROR_NO_CONTEXT;
258    
259     if (ddata.active) {
260     ddata.active->num_recv_packets ++;
261     rohc_debugf(2,"State in decomp %d\n",ddata.active->state );
262     }
263    
264     if (ret >= 0) {
265     if (!ddata.active) {
266     rohc_debugf(1, "decompress: ddata.active == null when ret >=0!\n");
267     } else {
268     struct sd_context *c = ddata.active;
269     c->total_uncompressed_size += ret;
270     c->total_compressed_size += isize;
271    
272     if (state->compressor) {
273     state->compressor->num_packets ++;
274     state->compressor->total_uncompressed_size += ret;
275     state->compressor->total_compressed_size += isize;
276     }
277    
278     c_add_wlsb(c->total_16_uncompressed, 0, 0, ret);
279     c_add_wlsb(c->total_16_compressed, 0,0, isize);
280     }
281     } else if (ddata.active) {
282     ddata.active->num_decomp_failures ++;
283     }
284    
285     //return ret;
286    
287     switch(ret)
288     {
289     case ROHC_ERROR_PACKAGE_FAILED:
290     case ROHC_ERROR:
291     state->statistics.packets_failed_package++;
292     ddata.active->curval += state->errval;
293     if(ddata.active->curval >= state->maxval) {
294     ddata.active->curval = 0;
295     d_operation_mode_feedback(state, ROHC_ERROR_PACKAGE_FAILED, ddata.cid, ddata.addcidUsed, ddata.largecidUsed, ddata.active->mode, ddata.active);
296     }
297     break;
298    
299     case ROHC_ERROR_NO_CONTEXT:
300     state->statistics.packets_failed_no_context++;
301     state->curval += state->errval;
302     if(state->curval >= state->maxval) {
303     state->curval = 0;
304     d_operation_mode_feedback(state, ROHC_ERROR_NO_CONTEXT, ddata.cid, ddata.addcidUsed, ddata.largecidUsed, ROHC_O_MODE, NULL);
305     }
306     break;
307    
308     case ROHC_FEEDBACK_ONLY:
309     state->statistics.packets_feedback++;
310     break;
311    
312     case ROHC_ERROR_CRC:
313     state->statistics.packets_failed_crc++;
314     ddata.active->curval += state->errval;
315     rohc_debugf(2,"feedback curr %d\n", ddata.active->curval);
316     rohc_debugf(2,"feedback max %d\n", state->maxval);
317     if(ddata.active->curval >= state->maxval) {
318     ddata.active->curval = 0;
319     d_operation_mode_feedback(state, ROHC_ERROR_CRC, ddata.cid, ddata.addcidUsed, ddata.largecidUsed, ddata.active->mode, ddata.active);
320     }
321     break;
322    
323     default: // ROHC_OK_NO_DATA, ROHC_OK
324     state->curval -= state->okval; // framework (S-NACK)
325     ddata.active->curval -= state->okval; // context (NACK)
326     rohc_debugf(2,"feedback curr %d\n", ddata.active->curval);
327     if(state->curval < 0)
328     state->curval = 0;
329    
330     if(ddata.active->curval < 0)
331     ddata.active->curval = 0;
332    
333     rohc_debugf(2,"feedback curr %d\n", ddata.active->curval);
334     if(ddata.active->mode == ROHC_U_MODE) {
335     ddata.active->mode = ROHC_O_MODE; // switch active context to o-mode
336     d_operation_mode_feedback(state, ROHC_OK, ddata.cid, ddata.addcidUsed, ddata.largecidUsed, ddata.active->mode, ddata.active);
337     }
338     break;
339     }
340     return(ret);
341     }
342     //----------------------------------------------------------------------------------------------------------------------------------
343     // To decompress both large and small cid package
344     //----------------------------------------------------------------------------------------------------------------------------------
345     int rohc_decompress_both(struct sd_rohc * state, unsigned char * ibuf, int isize, unsigned char * obuf, int osize, int large)
346     {
347     state->medium->cid_type = large ? ROHC_LARGE_CID : ROHC_SMALL_CID;
348    
349     return rohc_decompress(state, ibuf, isize, obuf, osize);
350     }
351     //----------------------------------------------------------------------------------------------------------------------------------
352     // Decode feedback and context-id if it exist
353     // Param state: pointer to decompressor
354     // Param walk: pointer to incoming packet
355     // Param isize: size of incoming packet
356     // Return: context-id if found, else rohc_feedback_only
357     //----------------------------------------------------------------------------------------------------------------------------------
358     int d_decode_feedback_first(struct sd_rohc * state, unsigned char ** walk, const int isize)
359     {
360     int cid = 0, i, fbloop = 1;
361     unsigned char * startpos = *walk;
362    
363     for(i=0; i<isize; i++) // remove all padded octets
364     if(d_is_paddning(*walk))
365     (*walk)++;
366     else
367     break;
368     while(fbloop) {
369     fbloop = 0;
370     if(d_is_add_cid(*walk)) { // if addcid - extract value
371     cid = d_decode_add_cid(*walk);
372     (*walk)++;
373     }
374     if(d_is_feedback(*walk)) { // is it feedback?
375     if(cid>0)
376     return(ROHC_ERROR_NO_CONTEXT);
377     else
378     *walk += d_decode_feedback(state, *walk);
379     fbloop = 1; // feedback found, keep looping
380     }
381     if((*walk)-startpos >= isize) // end of package
382     return(ROHC_FEEDBACK_ONLY);
383     }
384     return(cid);
385     }
386     //----------------------------------------------------------------------------------------------------------------------------------
387     // Main function for decompressing a ROHC-packet.
388     // Param state: pointer to decompressor
389     // Param ibuf: pointer to incoming packet
390     // Param isize: size of incoming packet
391     // Param obuf: pointer to output buffer
392     // Param osize: size of output buffer
393     // Param ddata: struct that holds important information to pass between several functions
394     // Return: size of decompressed packet
395     //----------------------------------------------------------------------------------------------------------------------------------
396     int d_decode_header(struct sd_rohc * state, unsigned char * ibuf, int isize, unsigned char * obuf, int osize, struct sd_decode_data * ddata)
397     {
398     int largecid=0, size, irdynvar=0, casenew=0;
399    
400     struct s_profile * profile;
401     unsigned char * walk = ibuf;
402    
403     if(isize < 2)
404     return(ROHC_ERROR_NO_CONTEXT);
405     ddata->cid = d_decode_feedback_first(state, &walk, isize);
406     if(ddata->cid == ROHC_FEEDBACK_ONLY || ddata->cid == ROHC_ERROR_NO_CONTEXT)
407     return(ddata->cid);
408    
409     if(ddata->cid > 0 && state->medium->cid_type == ROHC_SMALL_CID)
410     ddata->addcidUsed=1;
411    
412     if(!ddata->addcidUsed && state->medium->cid_type == ROHC_LARGE_CID) { // check if large cids are used
413     largecid = d_sdvalue_size(walk+1);
414     if(largecid >0 && largecid < 3) {
415     ddata->cid = d_sdvalue_decode(walk+1);
416     ddata->largecidUsed=1;
417     } else
418     return(ROHC_ERROR_NO_CONTEXT);
419     }
420    
421     if(d_is_ir(walk)) {
422     profile = find_profile(walk[largecid+1]);
423    
424     if(!rohc_ir_packet_crc_ok(walk, largecid, ddata->addcidUsed, profile))
425     return(ROHC_ERROR_CRC);
426    
427     if(ddata->cid >= state->context_array_size)
428     context_array_increase(state, ddata->cid);
429    
430     if(state->context[ddata->cid] && state->context[ddata->cid]->profile == profile) {
431     ddata->active = state->context[ddata->cid];
432     state->context[ddata->cid] = NULL;
433     } else {
434     casenew=1;
435     ddata->active = context_create(state, ddata->cid, profile);
436     if(!ddata->active)
437     return(ROHC_ERROR_NO_CONTEXT);
438     }
439    
440     ddata->active->num_recv_ir ++;
441     size = ddata->active->profile->decode_ir(state, ddata->active, walk+largecid+3, (isize-(walk-ibuf))-3-largecid, GET_BIT_0(walk), obuf);
442     if(size>0) {
443     context_free(state->context[ddata->cid]);
444     state->context[ddata->cid] = ddata->active;
445     return(size);
446     }
447     if(casenew)
448     context_free(ddata->active);
449     else
450     state->context[ddata->cid] = ddata->active;
451    
452     return(size);
453     } else {
454     ddata->active = find_context(state, ddata->cid); // find context
455     if(ddata->active && ddata->active->profile) { // context is valid
456     ddata->active->latest_used = get_milliseconds();
457     if(d_is_irdyn(walk)) {
458     ddata->active->num_recv_ir_dyn ++;
459     profile = find_profile(walk[largecid+1]);
460     if(profile != ddata->active->profile) { // if IR-DYN changes profile, make comp. transit to NO_CONTEXT-state
461     state->curval = state->maxval;
462     rohc_debugf(2,"IR-DYN changed profile, sending S-NACK.\n");
463     return(ROHC_ERROR_NO_CONTEXT);
464     }
465     if(!rohc_ir_dyn_packet_crc_ok(walk, largecid, ddata->addcidUsed, profile, ddata->active))
466     return(ROHC_ERROR_CRC);
467     irdynvar += 2;
468     }
469     return(ddata->active->profile->decode(state, ddata->active, walk, (isize-(walk-ibuf)), (ddata->largecidUsed ? (1+largecid+irdynvar) : 1+irdynvar), obuf));
470     } else
471     return(ROHC_ERROR_NO_CONTEXT);
472     }
473     return(ROHC_ERROR_NO_CONTEXT);
474     }
475     //----------------------------------------------------------------------------------------------------------------------------------
476     // Decode the Feedback
477     // Param state: pointer to decompressor
478     // Param ibuf: pointer to incoming packet
479     // Return: feedback size including feedback head
480     //----------------------------------------------------------------------------------------------------------------------------------
481     int d_decode_feedback(struct sd_rohc * state, unsigned char * ibuf)
482     {
483     int feedbacksize, head;
484     feedbacksize = d_feedback_size(ibuf); // extract the size of the feedback
485     head = d_feedback_headersize(ibuf); // point to feedback data
486     ibuf += head;
487     #ifdef USER_SPACE
488     feedbackRedir(ibuf, feedbacksize); // if user space application is running, send feedback to it..
489     #else
490     //passFeedback(ibuf, feedbacksize); // ..else pass it on to the compressor
491     if (state->compressor)
492     c_deliver_feedback(state->compressor, ibuf, feedbacksize);
493     #endif
494    
495     return(feedbacksize + head);
496     }
497     //----------------------------------------------------------------------------------------------------------------------------------
498     // Find profile with a certain id
499     // Param id: profile id to find
500     // Return: pointer to the matching profile
501     //----------------------------------------------------------------------------------------------------------------------------------
502     struct s_profile * find_profile(int id)
503     {
504     if(id==0)
505     return uncompressed_profile_create();
506     else if(id==2)
507     return udp_profile_create();
508     else if(id==4)
509     return iponly_profile_create();
510     else if(id==8)
511     return udp_lite_profile_create();
512     else
513     return uncompressed_profile_create();
514     }
515     //----------------------------------------------------------------------------------------------------------------------------------
516     // CRC check on IR-packets
517     // Param walk: pointer to incoming packet
518     // Param largecid: largecid value
519     // Param addcidUsed: value of addcidUsed, if 1 then addcid is used, else 0
520     // Param profile: pointer to profile of packet
521     // Return: 1 if CRC is OK, else 0
522     //----------------------------------------------------------------------------------------------------------------------------------
523     int rohc_ir_packet_crc_ok(unsigned char * walk, const int largecid, const int addcidUsed, const struct s_profile * profile)
524     {
525     int realcrc, crc;
526    
527     realcrc = walk[largecid+2];
528     walk[largecid+2] = 0;
529     if(profile->id==0)
530     crc = crc_calculate(CRC_TYPE_8, walk-addcidUsed, profile->detect_ir_size(walk, largecid+1)+2+largecid+addcidUsed);
531     else
532     crc = crc_calculate(CRC_TYPE_8, walk-addcidUsed, profile->detect_ir_size(walk, largecid+1)+3+largecid+addcidUsed);
533     walk[largecid+2] = realcrc;
534     if(crc != realcrc) {
535     rohc_debugf(0,"ROHC Decompress IR: CRC FAILED! SKA: %i, �: %i\n", realcrc, crc);
536     return(0);
537     }
538     rohc_debugf(2,"ROHC Decompress IR: CRC OK!\n");
539    
540     return(1);
541     }
542     //----------------------------------------------------------------------------------------------------------------------------------
543     // CRC check on IR-DYN packets
544     // Param walk: pointer to incoming packet
545     // Param largecid: largecid value'
546     // Param addcidUsed: value of addcidUsed'
547     // Param profile: pointer to profile of packet
548     // Return: 1 if CRC is OK, else 0
549     //----------------------------------------------------------------------------------------------------------------------------------
550     int rohc_ir_dyn_packet_crc_ok(unsigned char * walk, const int largecid, const int addcidUsed, const struct s_profile * profile, struct sd_context * context)
551     {
552     int realcrc, crc;
553    
554     realcrc = walk[largecid+2];
555     walk[largecid+2] = 0;
556     crc = crc_calculate(CRC_TYPE_8, walk-addcidUsed, profile->detect_ir_dyn_size(walk, context)+3+largecid+addcidUsed);
557     walk[largecid+2] = realcrc;
558     if(crc != realcrc) {
559     rohc_debugf(0,"ROHC Decompress IR_DYN: CRC FAILED! SKA: %i, �: %i\n", realcrc, crc);
560     return(0);
561     }
562     rohc_debugf(2,"ROHC Decompress IR_DYN: CRC OK!\n");
563    
564     return(1);
565     }
566     //----------------------------------------------------------------------------------------------------------------------------------
567     // Send Feedback depending on Mode: Unidirectional, Optimistic or Reliable Mode
568     // Param state: pointer to decompressor
569     // Param rohc_status: type of feedback to send; 0 = OK (ack), -1 = ContextInvalid (S-nack), -2 = PackageFailed (Nack)
570     // Param cid: context-id value
571     // Param addcidUsed: ==1 if addcid is used
572     // Param largecidUsed: ==1 if largecid is used
573     // Param mode: mode that ROHC operates in; U-, O- or R-MODE
574     // Param ctxt: active/current context
575     //----------------------------------------------------------------------------------------------------------------------------------
576     void d_operation_mode_feedback(struct sd_rohc * state, int rohc_status, int cid, int addcidUsed, int largecidUsed, int mode, struct sd_context * ctxt)
577     {
578     struct sd_feedback sfeedback;
579     char * feedback;
580     int feedbacksize;
581    
582     switch(mode)
583     {
584     case ROHC_U_MODE:
585     // no feedback needed
586     //break;
587     case ROHC_O_MODE:
588     switch(rohc_status)
589     {
590     case ROHC_OK:
591     f_feedback2(ACKTYPE_ACK, ctxt->mode, ctxt->profile->get_sn(ctxt), &sfeedback);
592     feedback = f_wrap_feedback(&sfeedback, cid, largecidUsed, WITH_CRC, &feedbacksize);
593     if(!feedback) {
594     rohc_debugf(0,"Feedback: ACK FAILED!\n");
595     return;
596     }
597     ctxt->num_sent_feedbacks++;
598     #ifdef USER_SPACE
599     rohc_debugf(2,"Feedback send to testapp\n");
600     feedbackRedir_piggy(feedback, feedbacksize);
601     #else
602     if(state->compressor)
603     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
604     #endif
605     kfree(feedback);
606     break;
607     case ROHC_ERROR_NO_CONTEXT:
608     f_feedback2(ACKTYPE_STATIC_NACK, ROHC_O_MODE, 0, &sfeedback);
609     f_add_option(&sfeedback, OPT_TYPE_SN_NOT_VALID, NULL);
610     feedback = f_wrap_feedback(&sfeedback, cid, largecidUsed, NO_CRC, &feedbacksize);
611     if(!feedback) {
612     rohc_debugf(0,"Feedback: ACK FAILED!\n");
613     return;
614     }
615     //ctxt->num_sent_feedbacks++;
616     #ifdef USER_SPACE
617     rohc_debugf(2,"Feedback send to testapp\n");
618     feedbackRedir_piggy(feedback, feedbacksize);
619     #else
620     if(state->compressor)
621     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
622     #endif
623     kfree(feedback);
624     break;
625     case ROHC_ERROR_PACKAGE_FAILED:
626     case ROHC_ERROR_CRC:
627     ctxt->num_sent_feedbacks++;
628     switch(ctxt->state)
629     {
630     case ROHC_NO_CONTEXT:
631     rohc_debugf(2,"No context\n");
632     f_feedback2(ACKTYPE_STATIC_NACK, ctxt->mode, ctxt->profile->get_sn(ctxt), &sfeedback);
633     feedback = f_wrap_feedback(&sfeedback, cid, largecidUsed, WITH_CRC, &feedbacksize);
634     if(!feedback) {
635     rohc_debugf(0,"Feedback: S-NACK (PF/CRC) FAILED!\n");
636     return;
637     }
638     #ifdef USER_SPACE
639     rohc_debugf(2,"Feedback send to testapp\n");
640     feedbackRedir_piggy(feedback, feedbacksize);
641     #else
642     if(state->compressor)
643     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
644     #endif
645     kfree(feedback);
646     break;
647     case ROHC_STATIC_CONTEXT:
648     case ROHC_FULL_CONTEXT:
649    
650     f_feedback2(ACKTYPE_NACK, ctxt->mode, ctxt->profile->get_sn(ctxt), &sfeedback);
651     feedback = f_wrap_feedback(&sfeedback, cid, largecidUsed, WITH_CRC, &feedbacksize);
652     if(!feedback) {
653     rohc_debugf(0,"Feedback: S-NACK (NC/SC) FAILED!\n");
654     return;
655     }
656     #ifdef USER_SPACE
657     rohc_debugf(2,"Feedback send to testapp\n");
658     feedbackRedir_piggy(feedback, feedbacksize);
659     #else
660     if(state->compressor)
661     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
662     #endif
663     if(ctxt->state == ROHC_STATIC_CONTEXT)
664     ctxt->state = ROHC_NO_CONTEXT;
665     if(ctxt->state == ROHC_FULL_CONTEXT)
666     ctxt->state = ROHC_STATIC_CONTEXT;
667     kfree(feedback);
668     break;
669     default:
670     break;
671     }
672     break;
673     }
674     break;
675     case ROHC_R_MODE:
676     // send feedback (not supported for now)
677     break;
678     }
679     }
680     //----------------------------------------------------------------------------------------------------------------------------------
681     // Clear all the statistics
682     // Param state: pointer to decompressor
683     //----------------------------------------------------------------------------------------------------------------------------------
684     void clear_statistics(struct sd_rohc * state)
685     {
686     state->statistics.packets_received = 0;
687     state->statistics.packets_failed_crc = 0;
688     state->statistics.packets_failed_no_context = 0;
689     state->statistics.packets_failed_package = 0;
690     state->statistics.packets_feedback = 0;
691     }
692    
693     //----------------------------------------------------------------------------------------------------------------------------------
694     // Store decompression statistics for a decompressor to the buffer
695     // Param decomp: pointer to the decompressor
696     // Param buffer:
697     //----------------------------------------------------------------------------------------------------------------------------------
698     /* Store decompression statistics for a decompressor to the buffer */
699     int rohc_d_statistics(struct sd_rohc *decomp, char *buffer)
700     {
701     struct s_profile *p;
702     int i;
703    
704     // Decompressor profiles
705     for (i=0; i<D_NUM_PROFILES; i++) {
706     p = d_profiles[i];
707    
708     sprintf(buffer, "%s\n%s\n", buffer, "---Profile");
709     sprintf(buffer, "%sPROFILE NO:%d\n", buffer, p->id);
710     sprintf(buffer, "%sACTIVE:%s\n", buffer, "YES");
711     sprintf(buffer, "%sVERSION NO:%s\n", buffer, p->version);
712     sprintf(buffer, "%sPROFILE TYPE:%s\n", buffer, p->description);
713    
714     }
715    
716     return strlen(buffer);
717     }
718    
719     //----------------------------------------------------------------------------------------------------------------------------------
720     // Decompressor Contexts
721     // Param decomp: pointer to the decompressor
722     // Param index:
723     // Param buffer:
724     //----------------------------------------------------------------------------------------------------------------------------------
725     int rohc_d_context(struct sd_rohc *decomp, int index, char *buffer) {
726     char *modes[4]= {"error", "U-mode", "O-mode", "R-mode"};
727     char *states[4] = {"error", "NC", "SC", "FC"};
728     char *save;
729     struct sd_context *c;
730     int v;
731    
732     if (index >= decomp->context_array_size)
733     return -2;
734    
735     c = decomp->context[index];
736     if (!c || !c->profile)
737     return -1;
738    
739     save = buffer;
740    
741     buffer += strlen(buffer);
742     sprintf(buffer, "\n---Context\n");
743     buffer += strlen(buffer);
744     sprintf(buffer, "CONTEXTTYPE:Decompressor\n");
745     buffer += strlen(buffer);
746     sprintf(buffer, "CID:%d\n", index);
747     buffer += strlen(buffer);
748     sprintf(buffer, "CID_STATE:%s\n", "USED");
749     buffer += strlen(buffer);
750     sprintf(buffer, "STATE:%s\n", states[c->state]);
751     buffer += strlen(buffer);
752     sprintf(buffer, "MODE:%s\n", modes[c->mode]);
753     buffer += strlen(buffer);
754     sprintf(buffer, "PROFILE:%s\n", c->profile->description);
755     buffer += strlen(buffer);
756    
757     if (c->total_uncompressed_size != 0)
758     v = (100*c->total_compressed_size) / c->total_uncompressed_size;
759     else
760     v = 0;
761     if (v < 0) {
762     rohc_debugf(0, "decomp: total_compressed_size=%d total_uncompressed_size=%d\n", c->total_compressed_size, c->total_uncompressed_size);
763     }
764     sprintf(buffer, "TOTALCOMPRATIOALLPACK:%d%%\n", v);
765     buffer += strlen(buffer);
766    
767     if (c->header_uncompressed_size != 0)
768     v = (100*c->header_compressed_size) / c->header_uncompressed_size;
769     else
770     v = 0;
771     sprintf(buffer, "TOTALCOMPRATIOALLPACKHEAD:%d%%\n", v);
772     buffer += strlen(buffer);
773    
774     v = c->total_compressed_size/c->num_recv_packets;
775     sprintf(buffer, "MEANCOMPPACKSIZEALLPACK:%d\n", v);
776     buffer += strlen(buffer);
777    
778     v = c->header_compressed_size/c->num_recv_packets;
779     sprintf(buffer, "MEANHEADSIZEALLCOMPHEAD:%d\n", v);
780     buffer += strlen(buffer);
781    
782     v = c_sum_wlsb(c->total_16_uncompressed);
783     if (v != 0)
784     v = (100 * c_sum_wlsb(c->total_16_compressed)) / v;
785     sprintf(buffer, "COMPRATIOLAST16PACK:%d%%\n", v);
786     buffer += strlen(buffer);
787    
788     v = c_sum_wlsb(c->header_16_uncompressed);
789     if (v != 0)
790     v = (100 * c_sum_wlsb(c->header_16_compressed)) / v;
791     sprintf(buffer, "COMPRATIOLAST16PACKHEAD:%d%%\n", v);
792     buffer += strlen(buffer);
793    
794     v = c_mean_wlsb(c->total_16_compressed);
795     sprintf(buffer, "MEANCOMPPACKSIZELAST16PACK:%d\n", v);
796     buffer += strlen(buffer);
797    
798     v = c_mean_wlsb(c->header_16_compressed);
799     sprintf(buffer, "MEANHEADSIZELAST16COMPHEAD:%d\n", v);
800     buffer += strlen(buffer);
801    
802     sprintf(buffer, "CONTEXTACTIVATIONTIME:%d\n", (get_milliseconds() - c->first_used) / 1000 );
803     buffer += strlen(buffer);
804     sprintf(buffer, "CONTEXTIDLETIME:%d\n", (get_milliseconds() - c->latest_used) / 1000);
805     buffer += strlen(buffer);
806    
807     sprintf(buffer, "NORECVPACKETS:%d\n", c->num_recv_packets);
808     buffer += strlen(buffer);
809     sprintf(buffer, "NORECVIRPACKETS:%d\n", c->num_recv_ir);
810     buffer += strlen(buffer);
811     sprintf(buffer, "NORECVIRDYNPACKETS:%d\n", c->num_recv_ir_dyn);
812     buffer += strlen(buffer);
813     sprintf(buffer, "NOSENTFEEDBACKS:%d\n", c->num_sent_feedbacks);
814     buffer += strlen(buffer);
815     sprintf(buffer, "NODECOMPFAILURES:%d\n", c->num_decomp_failures);
816     buffer += strlen(buffer);
817     sprintf(buffer, "NODECOMPREPAIRS:%d\n", c->num_decomp_repairs);
818     buffer += strlen(buffer);
819    
820     return strlen(save);
821     }
822    
823     //----------------------------------------------------------------------------------------------------------------------------------
824     // Create an ACK-packet telling the compressor to change state
825     // Param state: pointer to decompressor
826     // Param ctxt: pointer to active context
827     //----------------------------------------------------------------------------------------------------------------------------------
828     void d_change_mode_feedback(struct sd_rohc * state, struct sd_context * ctxt)
829     {
830     struct sd_feedback sfeedback;
831     int cid, feedbacksize;
832     char * feedback;
833    
834     for(cid=0; cid < state->context_array_size; cid++)
835     if(ctxt == state->context[cid])
836     break;
837     if(cid >= state->context_array_size)
838     return;
839    
840     f_feedback2(ACKTYPE_ACK, ctxt->mode, ctxt->profile->get_sn(ctxt), &sfeedback);
841     feedback = f_wrap_feedback(&sfeedback, cid, (state->medium->cid_type == ROHC_LARGE_CID ? 1 : 0), WITH_CRC, &feedbacksize);
842    
843     if(!feedback) {
844     rohc_debugf(0,"Feedback [d_change_mode_feedback()]: ACK FAILED!\n");
845     return;
846     }
847     #ifdef USER_SPACE
848     rohc_debugf(2,"Feedback [ACK] sent to testapp.\n");
849     feedbackRedir_piggy(feedback, feedbacksize);
850     #else
851     if(state->compressor)
852     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
853     #endif
854     kfree(feedback);
855     }
856     //----------------------------------------------------------------------------------------------------------------------------------
857     // Update feedback interval with data from the gui
858     // Param state: pointer to the decompressor
859     // Param feedback_maxval: the value from the gui
860     //----------------------------------------------------------------------------------------------------------------------------------
861     void usergui_interactions(struct sd_rohc * state, int feedback_maxval)
862     {
863     state->maxval = feedback_maxval*100;
864     }
865     //----------------------------------------------------------------------------------------------------------------------------------