ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/decomp.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

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