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, 1 month 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

# Content
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 */
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
38 #include "c_util.h"
39
40 //----------------------------------------------------------------------------------------------------------------------------------
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 //----------------------------------------------------------------------------------------------------------------------------------