ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/c_udp_lite.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 Implementation of the udp-lite profile (compressor)
32 */
33
34 #include <linux/ip.h>
35
36 #include "rohc.h"
37 #include "comp.h"
38 #include "c_util.h"
39
40
41
42 static const char *udp_lite_packet_types[] = {
43 "IR", "IRDYN", "OU-0", "OU-1", "OU-2"
44 };
45
46
47 static const char *udp_lite_extension_types[] = {
48 "NOEXT", "EXT0", "EXT1", "EXT2", "EXT3"
49 };
50
51 #define UDP_LITE_PRNR 254
52
53 #define MAX_LITE_COUNT 2
54
55 /*
56 Structure that contain counters, flags and structures that need to saved between different
57 packages. A context have a structure like this for the two first ip-headers.
58 */
59 struct sc_udp_lite_header
60 {
61 struct sc_wlsb *ip_id_window;
62 struct iphdr old_ip;
63
64 int tos_count, ttl_count, df_count, protocol_count;
65 int rnd_count, nbo_count;
66 int old_rnd,old_nbo;
67 int id_delta;
68
69 };
70 /*
71 Structure that contain variables that are temporar, i.e. they will only be jused in this
72 packet, they have to be reinitilized every time a new packet arrive.
73 */
74 struct udp_lite_tmp_variables{
75 // The following variables are set in encode
76 int nr_of_ip_hdr;
77 unsigned short changed_fields;
78 unsigned short changed_fields2;
79 int send_static;
80 int send_dynamic;
81 int nr_ip_id_bits;
82 int nr_sn_bits;
83 int nr_ip_id_bits2;
84 int packet_type;
85 int max_size;
86
87 int udp_size;
88 };
89
90 /*
91 Structure that contain counters, flags and structures that need to saved between different
92 packages. Every context have one of these
93 */
94 struct sc_udp_lite_context {
95 unsigned int sn;
96 struct sc_wlsb *sn_window;
97
98 int ir_count, fo_count, so_count;
99 int go_back_fo_count, go_back_ir_count, ir_dyn_count;
100 //int udp_checksum_change_count;
101 int cfp,cfi;
102 unsigned char FK;
103 int coverage_equal_count, coverage_inferred_count;
104 int tmp_coverage;
105 int sent_ce_on_count, sent_ce_off_count, sent_ce_only_count;
106
107 struct sc_udp_lite_header ip_flags, ip2_flags;
108 struct udphdr old_udp_lite;
109
110 struct udp_lite_tmp_variables tmp_variables;
111 int is_initialized; // if ip2 is initialized
112
113 };
114
115
116 static void udp_lite_decide_state(int send_udp_dynamic, struct sc_context *context);
117
118 static void c_udp_lite_update_variables(struct sc_context *context,const struct iphdr *ip,
119 const struct iphdr *ip2);
120
121 static int udp_lite_decide_packet(struct sc_context *context);
122
123 static int udp_lite_decide_FO_packet(struct sc_context *context);
124
125 static int udp_lite_decide_SO_packet(const struct sc_context *context);
126
127 static void udp_lite_periodic_down_transition(struct sc_context *context);
128
129 static int udp_lite_code_packet(struct sc_udp_lite_context *udp_lite_profile,const struct iphdr *ip,
130 const struct iphdr *ip2,const struct udphdr *udp_lite,unsigned char *dest, struct sc_context *context);
131
132
133 int udp_lite_code_IR_packet(struct sc_udp_lite_context *udp_lite_profile,const struct iphdr *ip,
134 const struct iphdr *ip2,const struct udphdr *udp_lite,unsigned char *dest,
135 struct sc_context *context,int counter,int first_position);
136 static int udp_lite_code_IR_DYN_packet(struct sc_udp_lite_context *udp_lite_profile,const struct iphdr *ip,
137 const struct iphdr *ip2,const struct udphdr *udp_lite,unsigned char *dest,
138 struct sc_context *context,int counter,int first_position);
139
140
141 static int udp_lite_code_static_part(struct sc_context *context,struct sc_udp_lite_header *ip_hdr_profile,const struct iphdr *ip,
142 unsigned char *dest, int counter);
143
144 static int udp_lite_code_static_udp_part(struct sc_context *context,
145 const struct udphdr *udp_lite,
146 unsigned char *dest,
147 int counter);
148
149 static int udp_lite_code_dynamic_part(struct sc_context *context,struct sc_udp_lite_header *ip_hdr_profile,const struct iphdr *ip,
150 unsigned char *dest, int counter,int *rnd, int *nbo);
151
152 static int udp_lite_code_dynamic_udp_part(struct sc_context *context,
153 const struct udphdr *udp_lite,
154 unsigned char *dest,
155 int counter);
156
157 static int udp_lite_code_UO0_packet(struct sc_context *context,const struct iphdr *ip,
158 unsigned char *dest, int counter,int first_position);
159
160 static int udp_lite_code_UO1_packet(struct sc_context *context,const struct iphdr *ip,
161 unsigned char *dest, int counter,int first_position );
162
163 static int udp_lite_code_UO2_packet(struct sc_context *context,struct sc_udp_lite_context *udp_lite_profile,
164 const struct iphdr *ip,const struct iphdr *ip2,unsigned char *dest, int counter,int first_position);
165
166 static int udp_lite_code_EXT0_packet(struct sc_context *context,const struct iphdr *ip,
167 unsigned char *dest, int counter);
168
169 static int udp_lite_code_EXT1_packet(struct sc_context *context,const struct iphdr *ip,
170 unsigned char *dest, int counter);
171
172 static int udp_lite_code_EXT2_packet(struct sc_context *context,struct sc_udp_lite_context *udp_lite_profile,
173 const struct iphdr *ip,
174 unsigned char *dest, int counter);
175
176 static int udp_lite_code_EXT3_packet(struct sc_context *context,struct sc_udp_lite_context *udp_lite_profile,
177 const struct iphdr *ip,const struct iphdr *ip2,
178 unsigned char *dest, int counter);
179
180 static int udp_lite_header_flags(struct sc_context *context,unsigned short changed_fields,struct sc_udp_lite_header *ip_hdr_profile,int counter,
181 boolean is_outer,int nr_ip_id_bits,const struct iphdr *ip,unsigned char *dest,int context_rnd,int context_nbo);
182
183 static int udp_lite_header_fields(struct sc_context *context,unsigned short changed_fields,struct sc_udp_lite_header *ip_hdr_profile,int counter,
184 boolean is_outer,int nr_ip_id_bits,const struct iphdr *ip,unsigned char *dest,int context_rnd);
185
186 static int udp_lite_decide_extension(struct sc_context *context);
187
188
189 static int udp_lite_changed_static_both_hdr(struct sc_context *context,
190 const struct iphdr *ip, const struct iphdr *ip2);
191
192 static int udp_lite_changed_static_one_hdr(unsigned short udp_lite_changed_fields,struct sc_udp_lite_header *ip_header, const struct iphdr *ip,
193 struct sc_context *context);
194
195
196 static int udp_lite_changed_dynamic_both_hdr(struct sc_context *context,
197 const struct iphdr *ip, const struct iphdr *ip2);
198
199 static int udp_lite_changed_dynamic_one_hdr(unsigned short udp_lite_changed_fields,struct sc_udp_lite_header *ip_hdr_profile, const struct iphdr *ip,
200 int context_rnd,int context_nbo,struct sc_context *context);
201
202 static int udp_lite_changed_udp_dynamic(struct sc_context *context,const struct udphdr *udp_lite);
203
204 static boolean udp_lite_is_changed(unsigned short udp_lite_changed_fields,unsigned short check_field);
205
206 static unsigned short udp_lite_changed_fields(struct sc_udp_lite_header *ip_hdr_profile,const struct iphdr *ip);
207
208 static void udp_lite_change_state(struct sc_context *, C_STATE);
209 static void udp_lite_change_mode(struct sc_context *, C_MODE);
210
211 static void udp_lite_check_ip_identification(struct sc_udp_lite_header *ip_hdr_profile, const struct iphdr *ip,int *context_rnd, int *context_nbo);
212
213 static void udp_lite_initiate_coverage_context(struct sc_udp_lite_context *udp_lite_profile,
214 const struct udphdr *udp_lite, unsigned char *dest, struct sc_context *context);
215
216 static boolean udp_lite_send_ce_packet(struct sc_udp_lite_context *udp_lite_profile,
217 const struct udphdr *udp_lite, unsigned char *dest,
218 struct sc_context *context);
219
220 /*
221 Initilize one ip-header context
222 */
223 void c_udp_lite_init_context(struct sc_udp_lite_header *ip_header,const struct iphdr *ip,int context_rnd,int context_nbo)
224 {
225 ip_header -> ip_id_window = c_create_wlsb(16,C_WINDOW_WIDTH,0);
226 ip_header->old_ip = *ip;
227 ip_header->old_rnd = context_rnd;
228 ip_header->old_nbo = context_nbo;
229 ip_header->tos_count = MAX_FO_COUNT;
230 ip_header->ttl_count = MAX_FO_COUNT;
231 ip_header->df_count = MAX_FO_COUNT;
232 ip_header->protocol_count = MAX_FO_COUNT;
233 ip_header->rnd_count = MAX_FO_COUNT;
234 ip_header->nbo_count = MAX_FO_COUNT;
235 }
236
237 /*
238 Initilize all temp variables
239 */
240 void c_udp_lite_init_tmp_variables(struct udp_lite_tmp_variables *udp_lite_tmp_variables){
241 udp_lite_tmp_variables->nr_of_ip_hdr = -1;
242 udp_lite_tmp_variables->changed_fields = -1;
243 udp_lite_tmp_variables->changed_fields2 = -1;
244 udp_lite_tmp_variables->send_static = -1;
245 udp_lite_tmp_variables->send_dynamic = -1;
246 udp_lite_tmp_variables->nr_ip_id_bits = -1;
247 udp_lite_tmp_variables->nr_sn_bits = -1;
248 udp_lite_tmp_variables->nr_ip_id_bits2 = -1;
249 udp_lite_tmp_variables->packet_type = -1;
250 udp_lite_tmp_variables->max_size = -1;
251 udp_lite_tmp_variables->udp_size = -1;
252
253 }
254
255 /*
256 Function to allocate for a new context, it aslo initilize alot of variables.
257 This function is one of the functions that must exist for the framework to
258 work. Please notice that a pointer to this function has to exist in the
259 sc_profile struct thatwe have in the bottom of this file.
260 */
261 int c_udp_lite_create(struct sc_context *context, const struct iphdr *ip)
262 {
263 struct sc_udp_lite_context *udp_lite_profile;
264 struct udphdr *udp_lite;
265 struct iphdr *ip2;
266 context->profile_context = kmalloc(sizeof(struct sc_udp_lite_context),GFP_ATOMIC);
267 if (context->profile_context == 0) {
268 rohc_debugf(0,"c_udp_lite_create(): no mem for profile context\n");
269 return 0;
270 }
271 udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
272 udp_lite_profile->sn = 0;
273
274 udp_lite_profile -> sn_window = c_create_wlsb(16,C_WINDOW_WIDTH,-1);
275
276 udp_lite_profile->cfp = 0;
277 udp_lite_profile->cfi = 0;
278 udp_lite_profile->FK = 0;
279 udp_lite_profile->coverage_equal_count = 0;
280 udp_lite_profile->coverage_inferred_count = 0;
281 udp_lite_profile->sent_ce_only_count = 0;
282 udp_lite_profile->sent_ce_on_count = MAX_IR_COUNT;
283 udp_lite_profile->sent_ce_off_count = MAX_IR_COUNT;
284
285
286 udp_lite_profile->ir_count = 0;
287 udp_lite_profile->fo_count = 0;
288 udp_lite_profile->so_count = 0;
289
290
291 if (ip->protocol == UDP_LITE_PRNR){
292 udp_lite = (struct udphdr *)(ip+1);
293 }else if(ip->protocol == 4){
294 ip2=(struct iphdr *)ip+1;
295 if(ip2->protocol == UDP_LITE_PRNR){
296 udp_lite = (struct udphdr *)(ip+2);
297 }
298 }
299 //udp_lite_profile->old_udp_lite = *udp_lite;
300
301 udp_lite_profile->go_back_fo_count = 0;
302 udp_lite_profile->go_back_ir_count = 0;
303 udp_lite_profile->ir_dyn_count = 0;
304 c_udp_lite_init_context(&udp_lite_profile->ip_flags,ip,context->rnd,context->nbo);
305 c_udp_lite_init_tmp_variables(&udp_lite_profile->tmp_variables);
306 udp_lite_profile->is_initialized = 0;
307 return 1;
308 }
309
310 /*
311 Function to deallocate a context.
312
313 This function is one of the functions that must exist for the framework to
314 work. Please notice that a pointer to this function has to exist in the
315 sc_profile struct thatwe have in the bottom of this file.
316 */
317 void c_udp_lite_destroy(struct sc_context *context){
318 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
319 c_destroy_wlsb(udp_lite_profile->ip_flags.ip_id_window);
320 c_destroy_wlsb(udp_lite_profile->sn_window);
321
322 if (context->profile_context != 0)
323 kfree(context->profile_context);
324
325 }
326
327 /*
328 The function are jused by the framework to check if a package belongs to this context
329 We check that its not framgmented. It is the source and destination addresses in the
330 ip-headers that decides if the package belong to this context, for udp the source and
331 destination ports also have to be the same for the package to be in the same context
332 as a cid.
333
334 This function is one of the functions that must exist for the framework to
335 work. Please notice that a pointer to this function has to exist in the
336 sc_profile struct that we have in the bottom of this file.
337 */
338 int c_udp_lite_check_context(struct sc_context *context, const struct iphdr *ip)
339 {
340 boolean is_ip_same;
341 boolean is_ip2_same;
342 boolean is_udp_same;
343 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
344 struct udphdr *udp_lite;
345 struct iphdr *ip2;
346 int reserved, dont_fragment, more_fragments, fragment_offset;
347 unsigned short fragment;
348
349 fragment = ntohs(ip->frag_off);
350
351 reserved = (fragment >> 15);
352 dont_fragment = (fragment >> 14) & 1;
353 more_fragments = (fragment >> 13) & 1;
354 fragment_offset = fragment & ((1<<14)-1);
355 if(reserved != 0 || more_fragments != 0 || fragment_offset != 0) {
356 rohc_debugf(0,"Fragment error (%d, %d, %d, %d)\n", reserved, dont_fragment, more_fragments, fragment_offset);
357 return -1;
358 }
359 is_ip_same = (udp_lite_profile->ip_flags.old_ip.saddr == ip->saddr) && (udp_lite_profile->ip_flags.old_ip.daddr == ip->daddr);
360 // 1
361 // udp 17
362 if (ip->protocol == UDP_LITE_PRNR){
363 udp_lite = (struct udphdr *)(ip+1);
364 is_udp_same = ((udp_lite_profile->old_udp_lite.source == udp_lite->source) &&
365 (udp_lite_profile->old_udp_lite.dest == udp_lite->dest));
366 return (is_ip_same && is_udp_same);
367
368 }else if(ip->protocol == 4){
369 ip2=(struct iphdr *)ip+1;
370 if(ip2->protocol == UDP_LITE_PRNR){
371 udp_lite = (struct udphdr *)(ip+2);
372 is_udp_same = ((udp_lite_profile->old_udp_lite.source == udp_lite->source) &&
373 (udp_lite_profile->old_udp_lite.dest == udp_lite->dest));
374 is_ip2_same = (udp_lite_profile->ip2_flags.old_ip.saddr == ip2->saddr) &&
375 (udp_lite_profile->ip2_flags.old_ip.daddr == ip2->daddr);
376 return (is_ip_same && is_ip2_same && is_udp_same);
377
378 }
379 else{
380 return 0;
381 }
382
383 }else{
384 return 0;
385 }
386
387 }
388
389
390
391 // Change the mode of this context
392 void udp_lite_change_mode(struct sc_context *c, C_MODE new_mode) {
393 if(c->c_mode != new_mode){
394 c->c_mode = new_mode;
395 udp_lite_change_state(c, IR);
396 }
397 }
398
399 // Change the state of this context
400 void udp_lite_change_state(struct sc_context *c, C_STATE new_state)
401 {
402 struct sc_udp_lite_context *ip = (struct sc_udp_lite_context *)c->profile_context;
403
404 // Reset counters only if different state
405 if (c->c_state != new_state) {
406 ip->ir_count = 0;
407 ip->fo_count = 0;
408 ip->so_count = 0;
409 }
410
411 c->c_state = new_state;
412 }
413
414 /*
415 Encode packages to a pattern decided by several different factors.
416 1. Checks if we have double ip-headers
417 2. Check if the ip identification field are random and if it has network byte order
418 3. Decide what state we have, ir,fo or so
419 4. Decide how many bits needed to send ip-id and sn fields and most imortant updating
420 the sliding windows.
421 5. Decide what packet to send.
422 6. Code the packet.
423
424
425 This function is one of the functions that must exist for the framework to
426 work. Please notice that a pointer to this function has to exist in the
427 sc_profile struct that we have in the bottom of this file.
428 */
429 int c_udp_lite_encode(struct sc_context *context,
430 const struct iphdr *ip,
431 int packet_size,
432 unsigned char *dest,
433 int max_size,
434 int *payload_offset)
435
436 {
437 int size;
438 int send_udp_dynamic;
439 int reserved, dont_fragment, more_fragments, fragment_offset;
440 unsigned short fragment;
441
442 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
443
444 struct iphdr *ip2=(struct iphdr *)ip+1;
445 struct udphdr *udp_lite;
446 udp_lite_profile->tmp_variables.nr_ip_id_bits2 = 0;
447 udp_lite_profile->tmp_variables.changed_fields2=0;
448 udp_lite_profile->tmp_variables.packet_type = c_IR;
449 udp_lite_profile->tmp_variables.max_size = max_size;
450 // 1
451 // udp UDP_LITE_PRNR
452 if (ip->protocol == UDP_LITE_PRNR){
453 ip2 = NULL;
454 udp_lite_profile->tmp_variables.nr_of_ip_hdr = 1;
455 //här kanske vi ska fråga andreas
456 udp_lite = (struct udphdr *)(ip+1);
457 udp_lite_profile->tmp_variables.udp_size = packet_size - sizeof(struct iphdr);
458 *payload_offset = 28;
459 }else if(ip->protocol == 4){
460 udp_lite_profile->tmp_variables.udp_size = packet_size - 2 * sizeof(struct iphdr);
461 if(!udp_lite_profile->is_initialized){
462 c_udp_lite_init_context(&udp_lite_profile->ip2_flags,ip2,context->rnd2,context->nbo2);
463 udp_lite_profile->is_initialized = 1;
464 }
465 if(ip2->protocol == UDP_LITE_PRNR){
466 udp_lite = (struct udphdr *)(ip+2);
467 *payload_offset = 48;
468 udp_lite_profile->tmp_variables.nr_of_ip_hdr = 2;
469 }
470 else{
471 return -1;
472 }
473 }else{
474 return -1;
475 }
476
477 if (udp_lite_profile == 0) {
478 rohc_debugf(0,"c_udp_lite_encode(): udp_lite_profile==null\n");
479 return 0;
480 }
481
482 fragment = ntohs(ip->frag_off);
483
484 reserved = (fragment >> 15);
485 dont_fragment = (fragment >> 14) & 1;
486 more_fragments = (fragment >> 13) & 1;
487 fragment_offset = fragment & ((1<<14)-1);
488 if(reserved != 0 || more_fragments != 0 || fragment_offset != 0) {
489 rohc_debugf(0,"Fragment error (%d, %d, %d, %d)\n", reserved, dont_fragment, more_fragments, fragment_offset);
490 return -1;
491 }
492
493
494 // 2. Check NBO and RND of IP-ID
495 if (udp_lite_profile->sn != 0){ // skip first packet
496 udp_lite_check_ip_identification(&udp_lite_profile->ip_flags,ip,&context->rnd, &context->nbo);
497 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
498 udp_lite_check_ip_identification(&udp_lite_profile->ip2_flags,ip2,&context->rnd2, &context->nbo2);
499 }
500 }
501 // Update the sequence number every time we encode something.
502 udp_lite_profile->sn = udp_lite_profile->sn + 1;
503 udp_lite_profile->tmp_variables.changed_fields = udp_lite_changed_fields(&udp_lite_profile->ip_flags,ip);
504 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
505 udp_lite_profile->tmp_variables.changed_fields2 = udp_lite_changed_fields(&udp_lite_profile->ip2_flags,ip2);
506 }
507
508 udp_lite_profile->tmp_variables.send_static = udp_lite_changed_static_both_hdr(context,ip,ip2);
509 udp_lite_profile->tmp_variables.send_dynamic = udp_lite_changed_dynamic_both_hdr(context,ip,ip2);
510 send_udp_dynamic = udp_lite_changed_udp_dynamic(context,udp_lite);
511
512 rohc_debugf(2,"send_static = %d, send_dynamic = %d\n", udp_lite_profile->tmp_variables.send_static,
513 udp_lite_profile->tmp_variables.send_dynamic);
514 // 3
515 udp_lite_decide_state(send_udp_dynamic,context);
516 rohc_debugf(2,"ip->id=%d context->sn=%d\n", ntohs(ip->id), udp_lite_profile->sn);
517
518 // 4
519 c_udp_lite_update_variables(context,ip,ip2);
520
521 // 5
522 udp_lite_profile->tmp_variables.packet_type = udp_lite_decide_packet(context);
523
524 // 6
525 size = udp_lite_code_packet(udp_lite_profile,ip,ip2,udp_lite,dest,context);
526
527 if(size < 0)
528 return -1;
529
530 if (udp_lite_profile->tmp_variables.packet_type == c_UO2) {
531 int extension = udp_lite_decide_extension(context);
532
533 rohc_debugf(1, "ROHC-UDP_LITE %s (%s): %d -> %d\n", udp_lite_packet_types[udp_lite_profile->tmp_variables.packet_type],
534 udp_lite_extension_types[extension],*payload_offset, size);
535 } else {
536 rohc_debugf(1, "ROHC-UDP_LITE %s: from %d -> %d\n", udp_lite_packet_types[udp_lite_profile->tmp_variables.packet_type],
537 *payload_offset, size);
538 }
539
540
541
542 udp_lite_profile->ip_flags.old_ip = *ip;
543
544 udp_lite_profile->ip_flags.old_rnd = context->rnd;
545 udp_lite_profile->ip_flags.old_nbo = context->nbo;
546
547 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
548 udp_lite_profile->ip2_flags.old_ip = *ip2;
549 udp_lite_profile->ip2_flags.old_rnd = context->rnd2;
550 udp_lite_profile->ip2_flags.old_nbo = context->nbo2;
551 }
552
553 if (udp_lite_profile->tmp_variables.packet_type == c_IR)
554 context->num_send_ir ++;
555 else if (udp_lite_profile->tmp_variables.packet_type == c_IRDYN)
556 context->num_send_ir_dyn ++;
557
558 return size;
559 }
560
561
562 /*
563 Function that update the profile when feedback has arrived.
564
565 This function is one of the functions that must exist for the framework to
566 work. Please notice that a pointer to this function has to exist in the
567 sc_profile struct that we have in the bottom of this file.
568 */
569 void c_udp_lite_feedback(struct sc_context *context, struct sc_feedback *feedback)
570 {
571 struct sc_udp_lite_context *ip_context = (struct sc_udp_lite_context *)context->profile_context;
572 unsigned char *p = feedback->data + feedback->specific_offset;
573
574 if (feedback->type == 1) { // ack
575 unsigned int sn = p[0];
576
577 c_ack_sn_wlsb(ip_context->ip_flags.ip_id_window, sn);
578 c_ack_sn_wlsb(ip_context->sn_window, sn);
579
580 } else if (feedback->type == 2) { // FEEDBACK-2
581 unsigned int crc = 0, crc_used=0;
582
583 int sn_not_valid = 0;
584 unsigned char mode = (p[0]>>4) & 3;
585 unsigned int sn = ((p[0] & 15) << 8) + p[1];
586 int remaining = feedback->specific_size-2;
587
588 p+=2;
589
590 while (remaining > 0) {
591 int opt = p[0]>>4;
592 int optlen = p[0] & 0x0f;
593
594 switch (opt) {
595 case 1: // CRC
596 crc = p[1];
597 crc_used = 1;
598 p[1] = 0; // set to zero for crc computation..
599 break;
600 //case 2: // Reject
601 //break;
602 case 3: // SN-Not-Valid
603 sn_not_valid=1;
604 break;
605 case 4: // SN -- TODO: how is several SN options combined?
606 sn = (sn<<8) + p[1];
607 break;
608 //case 7: // Loss
609 //break;
610 default:
611 rohc_debugf(0,"c_udp_lite_feedback(): Unknown feedback type: %d\n", opt);
612 break;
613 }
614
615 remaining -= 1 + optlen;
616 p += 1 + optlen;
617 }
618
619 if (crc_used) { // check crc..
620 if (crc_calculate(CRC_TYPE_8, feedback->data, feedback->size ) != crc) {
621 rohc_debugf(0,"c_udp_lite_feedback(): crc check failed..(size=%d)\n", feedback->size);
622 return;
623 }
624 }
625
626 if (mode != 0) {
627 if (crc_used) {
628 udp_lite_change_mode(context, mode);
629 rohc_debugf(1,"c_udp_lite_feedback(): changing mode to %d\n", mode);
630 } else {
631 rohc_debugf(0,"c_udp_lite_feedback(): mode change requested but no crc was given..\n");
632 }
633 }
634
635 switch (feedback->acktype) {
636 case ACK:
637 if (sn_not_valid == 0) {
638 c_ack_sn_wlsb(ip_context->ip_flags.ip_id_window, sn);
639 c_ack_sn_wlsb(ip_context->sn_window, sn);
640 }
641 break;
642
643 case NACK:
644 if (context->c_state == SO){
645 change_state(context, FO);
646 ip_context->ir_dyn_count = 0;
647 }
648 if(context->c_state == FO){
649 ip_context->ir_dyn_count = 0;
650 }
651 break;
652
653 case STATIC_NACK:
654 udp_lite_change_state(context, IR);
655 break;
656
657 case RESERVED:
658 rohc_debugf(0, "c_udp_lite_feedback(): reserved field used\n");
659 break;
660 }
661
662 } else {
663 rohc_debugf(0,"c_udp_lite_feedback(): Feedback type not implemented (%d)\n", feedback->type);
664 }
665
666 }
667
668 /*
669 Decide the state that that should be used for this packet
670 The three states are:
671 IR (initialization and refresh).
672 FO (first order).
673 SO (second order).
674 */
675 void udp_lite_decide_state(int send_udp_dynamic, struct sc_context *context)
676 {
677 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
678 int send_static = udp_lite_profile->tmp_variables.send_static;
679 int send_dynamic = udp_lite_profile->tmp_variables.send_dynamic;
680 if(context->c_state == IR && send_dynamic
681 && udp_lite_profile->ir_count >= MAX_IR_COUNT){
682 udp_lite_change_state(context, FO);
683 }else if(context->c_state == IR && send_static
684 && udp_lite_profile->ir_count >= MAX_IR_COUNT){
685 udp_lite_change_state(context, FO);
686 }else if (context->c_state == IR && udp_lite_profile->ir_count >= MAX_IR_COUNT) {
687 udp_lite_change_state(context, SO);
688 }else if (context->c_state == FO && send_dynamic
689 && udp_lite_profile->fo_count >= MAX_FO_COUNT) {
690 udp_lite_change_state(context, FO);
691 }else if (context->c_state == FO && send_static
692 && udp_lite_profile->fo_count >= MAX_FO_COUNT) {
693 udp_lite_change_state(context, FO);
694 }else if (context->c_state == FO && udp_lite_profile->fo_count >= MAX_FO_COUNT) {
695 udp_lite_change_state(context, SO);
696 }else if(context->c_state == SO && send_dynamic){
697 udp_lite_change_state(context, FO);
698 }else if(context->c_state == SO && send_static){
699 udp_lite_change_state(context, FO);
700 }
701 if(context->c_mode == U){
702 udp_lite_periodic_down_transition(context);
703 }
704
705 }
706
707 /*
708 A function just to update some variables, only used in encode. Everything in this
709 function could be in encode but to make it more readable we have it here instead.
710 */
711 void c_udp_lite_update_variables(struct sc_context *context,
712 const struct iphdr *ip,
713 const struct iphdr *ip2)
714 {
715 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
716 if (context->nbo)
717 udp_lite_profile->ip_flags.id_delta = (ntohs(ip->id) - udp_lite_profile->sn);
718 else
719 udp_lite_profile->ip_flags.id_delta = ip->id - udp_lite_profile->sn;
720
721 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
722 if (context->nbo2)
723 udp_lite_profile->ip2_flags.id_delta = (ntohs(ip2->id) - udp_lite_profile->sn);
724 else
725 udp_lite_profile->ip2_flags.id_delta = ip2->id - udp_lite_profile->sn;
726 }
727
728
729 rohc_debugf(2,"Get k\n");
730 rohc_debugf(2,"id_delta: %d\n",udp_lite_profile->ip_flags.id_delta);
731 rohc_debugf(2,"Given that sn: %d\n",udp_lite_profile->sn);
732 udp_lite_profile->tmp_variables.nr_ip_id_bits = c_get_k_wlsb(udp_lite_profile->ip_flags.ip_id_window, udp_lite_profile->ip_flags.id_delta);
733 udp_lite_profile->tmp_variables.nr_sn_bits = c_get_k_wlsb(udp_lite_profile->sn_window, udp_lite_profile->sn);
734
735 rohc_debugf(2,"Adding\n");
736 c_add_wlsb(udp_lite_profile->ip_flags.ip_id_window, udp_lite_profile->sn, 0, udp_lite_profile->ip_flags.id_delta); // TODO: replace 0 with time(0)
737 c_add_wlsb(udp_lite_profile->sn_window, udp_lite_profile->sn, 0, udp_lite_profile->sn); // TODO: replace 0 with time(0)
738
739 rohc_debugf(2,"ip_id bits=%d\n", udp_lite_profile->tmp_variables.nr_ip_id_bits);
740 rohc_debugf(2,"sn bits=%d\n", udp_lite_profile->tmp_variables.nr_sn_bits);
741 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
742 udp_lite_profile->tmp_variables.nr_ip_id_bits2 = c_get_k_wlsb(udp_lite_profile->ip2_flags.ip_id_window, udp_lite_profile->ip2_flags.id_delta);
743 rohc_debugf(2,"ip_id bits2=%d\n", udp_lite_profile->tmp_variables.nr_ip_id_bits2);
744 c_add_wlsb(udp_lite_profile->ip2_flags.ip_id_window, udp_lite_profile->sn, 0, udp_lite_profile->ip2_flags.id_delta); // TODO: replace 0 with time(0)
745 }
746 }
747
748 /*Function that change state periodicly after a certain number of packets */
749 void udp_lite_periodic_down_transition(struct sc_context *context)
750 {
751 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
752 if(udp_lite_profile->go_back_fo_count == CHANGE_TO_FO_COUNT){
753 udp_lite_profile->go_back_fo_count = 0;
754 udp_lite_profile->ir_dyn_count = 0;
755 udp_lite_change_state(context, FO);
756
757 } else if(udp_lite_profile->go_back_ir_count == CHANGE_TO_IR_COUNT){
758 udp_lite_profile->go_back_ir_count = 0;
759 udp_lite_change_state(context, IR);
760 }
761 if (context->c_state == SO)
762 udp_lite_profile->go_back_fo_count++;
763 if(context->c_state == SO || context->c_state == FO)
764 udp_lite_profile->go_back_ir_count++;
765 }
766
767 /*
768 Decide what packet to send in the different states,
769 In IR state, ir packets are used. In FO and SO the functions udp_lite_decide_FO_packet and udp_lite_decide_SO_packet is used.
770 */
771 int udp_lite_decide_packet(struct sc_context *context)
772 {
773 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
774 int packet_type=IR;
775 switch(context->c_state)
776 {
777 case IR:
778 rohc_debugf(2,"c_udp_lite_encode(): IR state\n");
779 udp_lite_profile->ir_count++;
780 packet_type = c_IR;
781 break;
782 case FO:
783 rohc_debugf(2,"c_udp_lite_encode(): FO state\n");
784 udp_lite_profile->fo_count++;
785 packet_type = udp_lite_decide_FO_packet(context);
786 break;
787
788 case SO:
789 rohc_debugf(2,"c_udp_lite_encode(): SO state\n");
790 udp_lite_profile->so_count++;
791 packet_type = udp_lite_decide_SO_packet(context);
792 break;
793 }
794 return packet_type;
795 }
796
797 /*
798 Decide which packet to send in first order state
799 The packets that can be used is IRDYN and UO2 packets.
800 */
801 int udp_lite_decide_FO_packet(struct sc_context *context)
802 {
803 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
804 if(udp_lite_profile->ir_dyn_count < MAX_FO_COUNT){
805 udp_lite_profile->ir_dyn_count++;
806 return c_IRDYN;
807 }else if (udp_lite_profile->tmp_variables.send_static) { // if static field changed we must go back to ir
808 return c_UO2;
809 }else if((udp_lite_profile->tmp_variables.nr_of_ip_hdr == 1 && udp_lite_profile->tmp_variables.send_dynamic > 2)){
810 return c_IRDYN;
811 }else if((udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1 && udp_lite_profile->tmp_variables.send_dynamic > 4)){
812 return c_IRDYN;
813 }
814 else{
815 return c_UO2;
816 }
817
818 }
819
820 /*
821 Decide which packet to send in second order state
822 Packet that can be used are UO0, UO1, UO2 with or without extensions.
823 */
824 int udp_lite_decide_SO_packet(const struct sc_context *context)
825 {
826 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
827 int nr_ip_id_bits = udp_lite_profile->tmp_variables.nr_ip_id_bits;
828 int nr_ip_id_bits2 = udp_lite_profile->tmp_variables.nr_ip_id_bits2;
829 int nr_sn_bits = udp_lite_profile->tmp_variables.nr_sn_bits;
830 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr == 1){
831 if(context->rnd == 1 && nr_sn_bits <= 4){
832 return c_UO0;
833 }
834 else if(nr_sn_bits <= 4 && nr_ip_id_bits == 0){
835 return c_UO0;
836 }
837 else if(nr_sn_bits == 5 && nr_ip_id_bits == 0){
838 return c_UO2;
839 }
840 else if(nr_sn_bits <= 5 && nr_ip_id_bits <= 6){
841 return c_UO1;
842 }
843 else{
844 return c_UO2;
845 }
846 }
847 else{
848 if(context->rnd == 1 && context->rnd2 == 1 && nr_sn_bits <= 4){
849 return c_UO0;
850 }
851 else if(nr_sn_bits <= 4 && (context->rnd == 1 || nr_ip_id_bits == 0)
852 && (context->rnd2 == 1 || nr_ip_id_bits2 ==0)){
853
854 return c_UO0;
855 }
856 else if(nr_sn_bits <= 5 && nr_ip_id_bits <= 6 && (context->rnd2 == 1 || nr_ip_id_bits2 == 0)){
857 return c_UO1;
858 }
859 else{
860 return c_UO2;
861 }
862 }
863 }
864
865 /*Code the given packet type*/
866
867 /*
868 Code the given packet type
869 Every given type has its own help function
870 The ir and ir-dyn packet are totally coded by their own functions. The general format
871 for other packets are coded in this function according to the following:
872
873 0 1 2 3 4 5 6 7
874 --- --- --- --- --- --- --- ---
875 1 : Add-CID octet : if for small CIDs and CID 1-15
876 +---+---+---+---+---+---+---+---+
877 2 | 1 1 1 1 1 0 F K | Outer packet type identifier
878 +---+---+---+---+---+---+---+---+
879 : :
880 3 / 0, 1, or 2 octets of CID / 1-2 octets if large CIDs
881 : :
882 +---+---+---+---+---+---+---+---+
883 4 | first octet of base header | (with type indication)
884 +---+---+---+---+---+---+---+---+
885 5 / remainder of base header / variable number of bits
886 +---+---+---+---+---+---+---+---+
887 : :
888 6 / Extension (see 5.7.5) / extension, if X = 1 in base header
889 : :
890 --- --- --- --- --- --- --- ---
891 : :
892 7 + IP-ID of outer IPv4 header + 2 octets, if value(RND2) = 1
893 : :
894 --- --- --- --- --- --- --- ---
895 8 / AH data for outer list / variable (see 5.8.4.2)
896 --- --- --- --- --- --- --- ---
897 : :
898 9 + GRE checksum (see 5.8.4.4) + 2 octets, if GRE flag C = 1
899 : :
900 --- --- --- --- --- --- --- ---
901 : :
902 10 + IP-ID of inner IPv4 header + 2 octets, if value(RND) = 1
903 : :
904 --- --- --- --- --- --- --- ---
905 11 / AH data for inner list / variable (see 5.8.4.2)
906 --- --- --- --- --- --- --- ---
907 : :
908 12 + GRE checksum (see 5.8.4.4) + 2 octets, if GRE flag C = 1
909 : :
910 --- --- --- --- --- --- --- ---
911 : List of :
912 13 / Dynamic chains / variable, given by static chain
913 : for additional IP headers : (includes no SN)
914 --- --- --- --- --- --- --- ---
915 : : 2 octets,
916 14 + UDP-Lite Checksum Coverage + if context(CFP) = 1 or
917 : : if packet type = CE
918 --- --- --- --- --- --- --- ---
919 : :
920 15 + UDP Checksum + 2 octets,
921 : :
922 --- --- --- --- --- --- --- ---
923
924 8, 9, 11, 12, 13 is not supported.
925 Each profile code 1, 2, 3, 4, 5, 6 is coded in each packets function
926 6, 9, 14, 15 is coded in this function
927 */
928 int udp_lite_code_packet(struct sc_udp_lite_context *udp_lite_profile,
929 const struct iphdr *ip,
930 const struct iphdr *ip2,
931 const struct udphdr *udp_lite,
932 unsigned char *dest,
933 struct sc_context *context)
934 {
935 int counter = 0;
936 int first_position;
937 boolean send_ce_packet;
938 //struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
939 //Both 1 and 3, 2 will be put on first_position
940 counter = code_cid_values(context,dest,udp_lite_profile->tmp_variables.max_size,&first_position);
941 rohc_debugf(2,"counter=%d, first_position=%d .\n",counter,first_position);
942 switch(udp_lite_profile->tmp_variables.packet_type){
943 case c_IR:
944 rohc_debugf(2,"udp_lite_code_packet(): IR packet..\n");
945 return udp_lite_code_IR_packet(udp_lite_profile,ip,ip2,udp_lite,
946 dest,context,counter,first_position);
947 break;
948 case c_IRDYN:
949 rohc_debugf(2,"udp_lite_code_packet(): IRDYN packet..\n");
950 return udp_lite_code_IR_DYN_packet(udp_lite_profile,ip,ip2,udp_lite,dest,
951 context,counter,first_position);
952 break;
953 }
954 send_ce_packet = udp_lite_send_ce_packet(udp_lite_profile,udp_lite,dest,context);
955 if(send_ce_packet){
956 rohc_debugf(2,"Sending ce-packet..\n");
957 // 2*
958 dest[first_position] = (0xf8 | udp_lite_profile->FK);
959 //Now the first_position will be on counter current position
960 //and counter must be increased
961 first_position = counter;
962 counter++;
963 }
964 else{
965 rohc_debugf(2,"Not ce-packet..\n");
966 }
967
968
969 switch(udp_lite_profile->tmp_variables.packet_type){
970 case c_UO0:
971 rohc_debugf(2,"udp_lite_code_packet(): OU-0 packet..\n");
972 counter = udp_lite_code_UO0_packet(context, ip, dest,
973 counter,first_position);
974 break;
975 case c_UO1:
976 rohc_debugf(2,"udp_lite_code_packet(): OU-1 packet..\n");
977 counter = udp_lite_code_UO1_packet(context, ip, dest,
978 counter,first_position);
979 break;
980
981 case c_UO2:
982 rohc_debugf(2,"udp_lite_code_packet(): OU-2 packet..\n");
983 counter = udp_lite_code_UO2_packet(context,udp_lite_profile,ip,ip2,dest,counter,first_position);
984 break;
985 default:
986 rohc_debugf(0,"udp_lite_code_packet(): Unknown packet..\n");
987 return -1;
988 }
989 rohc_debugf(2,"RND=%d RND2=%d\n",context->rnd, context->rnd2);
990
991 // 10
992 if(context->rnd == 1){
993 memcpy(&dest[counter], &ip->id, 2);
994 counter += 2;
995 }
996
997 // 7
998 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
999 if(context->rnd2 == 1){
1000 memcpy(&dest[counter], &ip2->id, 2);
1001 counter += 2;
1002 }
1003 }
1004 rohc_debugf(2,"cfp value: %d..\n", udp_lite_profile->cfp);
1005 // 14
1006 if((udp_lite_profile->cfp == 1) || send_ce_packet){
1007 memcpy(&dest[counter], &udp_lite->len, 2);
1008
1009 counter += 2;
1010 }
1011
1012 // 15
1013 memcpy(&dest[counter], &udp_lite->check, 2);
1014 counter += 2;
1015
1016
1017 return counter;
1018
1019 }
1020
1021
1022
1023 /*
1024 Code the IR-packet to this pattern:
1025
1026 IR packet (5.7.7.1):
1027
1028 0 1 2 3 4 5 6 7
1029 --- --- --- --- --- --- --- ---
1030 1 | Add-CID octet | if for small CIDs and CID != 0
1031 +---+---+---+---+---+---+---+---+
1032 2 | 1 1 1 1 1 1 0 | D |
1033 +---+---+---+---+---+---+---+---+
1034 | |
1035 3 / 0-2 octets of CID info / 1-2 octets if for large CIDs
1036 | |
1037 +---+---+---+---+---+---+---+---+
1038 4 | Profile | 1 octet
1039 +---+---+---+---+---+---+---+---+
1040 5 | CRC | 1 octet
1041 +---+---+---+---+---+---+---+---+
1042 | |
1043 6 | Static chain | variable length
1044 | |
1045 +---+---+---+---+---+---+---+---+
1046 | |
1047 7 | Dynamic chain | present if D = 1, variable length
1048 | |
1049 +---+---+---+---+---+---+---+---+
1050 | |
1051 | Payload | variable length
1052 | |
1053 - - - - - - - - - - - - - - - -
1054
1055 The numbers before every field is used to find where in the code we try
1056 to code that field.
1057 */
1058 int udp_lite_code_IR_packet(struct sc_udp_lite_context *udp_lite_profile,
1059 const struct iphdr *ip,
1060 const struct iphdr *ip2,
1061 const struct udphdr *udp_lite,
1062 unsigned char *dest,
1063 struct sc_context *context,
1064 int counter,
1065 int first_position)
1066
1067 {
1068 unsigned char type;
1069 int crc_position;
1070
1071
1072 udp_lite_initiate_coverage_context(udp_lite_profile,udp_lite,dest,context);
1073
1074 rohc_debugf(2,"Coding IR packet (cid=%d)\n", context->cid);
1075
1076 // 2
1077 type = 0xfc;
1078 //Always sends dynamic
1079 type += 1;
1080
1081
1082 dest[first_position] = type;
1083 // if large cid
1084 // Set profile_id and crc to zero so far
1085 // 3
1086 dest[counter] = context -> profile_id;
1087 counter++;
1088
1089 // 5
1090 // Becuase we calculate the crc over the ir packet with the crc field set to zero
1091 // The real crc is calculated in the end of this function
1092 crc_position = counter;
1093 dest[counter] = 0;
1094 counter++;
1095
1096 // 6
1097 counter = udp_lite_code_static_part(context,&udp_lite_profile->ip_flags,ip,dest, counter);
1098
1099 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
1100 counter = udp_lite_code_static_part(context,&udp_lite_profile->ip2_flags,ip2,dest,counter);
1101 }
1102 if(counter < 0)
1103 return -1;
1104 counter = udp_lite_code_static_udp_part(context,udp_lite,dest,counter);
1105
1106 // Add the dynamic part
1107 // Set type of service, time to live id, and some small flags
1108 //if(udp_lite_changed_dynamic_both_hdr(changed_fields,context) > 0){
1109 //rohc_debugf(1,"Crc length=%d\n", counter);
1110
1111
1112 // 7
1113
1114 //Observe that if we don't wan't dynamic part in ir-packet we should not send the following
1115 //******************************************************************************************************
1116 counter = udp_lite_code_dynamic_part(context,&udp_lite_profile->ip_flags,ip,dest,counter,&context->rnd,&context->nbo);
1117 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
1118 counter = udp_lite_code_dynamic_part(context,&udp_lite_profile->ip2_flags,ip2,dest,counter,&context->rnd2,&context->nbo2);
1119 }
1120 if(counter < 0)
1121 return -1;
1122 counter = udp_lite_code_dynamic_udp_part(context,udp_lite,dest,counter);
1123 //******************************************************************************************************
1124
1125
1126 //}
1127
1128 // 5 Count the crc and set the crc field to the checksum.
1129 rohc_debugf(2,"Crc length=%d\n", counter);
1130 dest[crc_position]= crc_calculate(CRC_TYPE_8,dest,counter);
1131 return counter;
1132
1133 }
1134 /*
1135 Code the IRDYN-packet to this pattern:
1136
1137 IR-dyn packet (5.7.7.2):
1138
1139 0 1 2 3 4 5 6 7
1140 --- --- --- --- --- --- --- ---
1141 1 : Add-CID octet : if for small CIDs and CID != 0
1142 +---+---+---+---+---+---+---+---+
1143 2 | 1 1 1 1 1 0 0 0 | IR-DYN packet type
1144 +---+---+---+---+---+---+---+---+
1145 : :
1146 3 / 0-2 octets of CID info / 1-2 octets if for large CIDs
1147 : :
1148 +---+---+---+---+---+---+---+---+
1149 4 | Profile | 1 octet
1150 +---+---+---+---+---+---+---+---+
1151 5 | CRC | 1 octet
1152 +---+---+---+---+---+---+---+---+
1153 | |
1154 6 / Dynamic chain / variable length
1155 | |
1156 +---+---+---+---+---+---+---+---+
1157 : :
1158 / Payload / variable length
1159 : :
1160 - - - - - - - - - - - - - - - -
1161
1162
1163 The numbers before every field is used to find where in the code we try
1164 to code that field.
1165
1166 */
1167 int udp_lite_code_IR_DYN_packet(struct sc_udp_lite_context *udp_lite_profile,
1168 const struct iphdr *ip,
1169 const struct iphdr *ip2,
1170 const struct udphdr *udp_lite,
1171 unsigned char *dest,
1172 struct sc_context *context,
1173 int counter,
1174 int first_position)
1175 {
1176 int crc_position;
1177 udp_lite_initiate_coverage_context(udp_lite_profile,udp_lite,dest,context);
1178 // 2
1179 dest[first_position] = 0xf8;
1180
1181 // 4
1182 dest[counter] = context -> profile_id;
1183 counter++;
1184
1185 // 5
1186 // Becuase we calculate the crc over the ir packet with the crc field set to zero
1187 // The real crc is calculated in the end of this function
1188 crc_position = counter;
1189 dest[counter] = 0;
1190 counter++;
1191
1192 // 6
1193 counter = udp_lite_code_dynamic_part(context,&udp_lite_profile->ip_flags,ip,dest,counter,&context->rnd,&context->nbo);
1194 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
1195 counter = udp_lite_code_dynamic_part(context,&udp_lite_profile->ip2_flags,ip2,dest,counter,&context->rnd2,&context->nbo2);
1196 }
1197 if(counter < 0)
1198 return -1;
1199 counter = udp_lite_code_dynamic_udp_part(context,udp_lite,dest,counter);
1200
1201 // 5
1202 // Count the crc and set the crc field to the checksum.
1203 dest[crc_position]= crc_calculate(CRC_TYPE_8,dest,counter);
1204 return counter;
1205 }
1206
1207
1208
1209
1210 /*
1211 Code the static part:
1212 Static part IPv4 (5.7.7.4):
1213
1214 +---+---+---+---+---+---+---+---+
1215 1 | Version = 4 | 0 |
1216 +---+---+---+---+---+---+---+---+
1217 2 | Protocol |
1218 +---+---+---+---+---+---+---+---+
1219 3 / Source Address / 4 octets
1220 +---+---+---+---+---+---+---+---+
1221 4 / Destination Address / 4 octets
1222 +---+---+---+---+---+---+---+---+
1223 */
1224 int udp_lite_code_static_part(struct sc_context *context,
1225 struct sc_udp_lite_header *ip_hdr_profile,
1226 const struct iphdr *ip,
1227 unsigned char *dest,
1228 int counter)
1229 {
1230
1231 // 1
1232 dest[counter] = 0x40;
1233 counter++;
1234
1235 // 2
1236 dest[counter] = ip -> protocol; rohc_debugf(3,"code_IR, protocol=%d\n", dest[counter]);
1237 counter++;
1238 ip_hdr_profile -> protocol_count++;
1239
1240 // 3
1241 memcpy(&dest[counter], &ip -> saddr, 4);
1242 counter += 4;
1243
1244 // 4
1245 memcpy(&dest[counter], &ip -> daddr, 4);
1246 counter += 4;
1247 return counter;
1248 }
1249
1250 /*
1251 Static part of udp_lite header (5.7.7.5):
1252
1253 +---+---+---+---+---+---+---+---+
1254 1 / Source Port / 2 octets
1255 +---+---+---+---+---+---+---+---+
1256 2 / Destination Port / 2 octets
1257 +---+---+---+---+---+---+---+---+
1258 */
1259 int udp_lite_code_static_udp_part(struct sc_context *context,
1260 const struct udphdr *udp_lite,
1261 unsigned char *dest,
1262 int counter)
1263 {
1264 // 1
1265 memcpy(&dest[counter], &udp_lite->source, 2);
1266 counter += 2;
1267
1268 // 2
1269 memcpy(&dest[counter], &udp_lite->dest, 2);
1270 counter += 2;
1271
1272 return counter;
1273 }
1274
1275 /*
1276 Code the dynamic part:
1277 Dynamic part IPv4 (5.7.7.4):
1278
1279 +---+---+---+---+---+---+---+---+
1280 1 | Type of Service |
1281 +---+---+---+---+---+---+---+---+
1282 2 | Time to Live |
1283 +---+---+---+---+---+---+---+---+
1284 3 / Identification / 2 octets
1285 +---+---+---+---+---+---+---+---+
1286 4 | DF|RND|NBO| 0 |
1287 +---+---+---+---+---+---+---+---+
1288 5 / Generic extension header list / variable length
1289 +---+---+---+---+---+---+---+---+
1290 */
1291 int udp_lite_code_dynamic_part(struct sc_context *context,
1292 struct sc_udp_lite_header *ip_hdr_profile,
1293 const struct iphdr *ip,
1294 unsigned char *dest,
1295 int counter,
1296 int *rnd,
1297 int *nbo)
1298 {
1299
1300 unsigned char df_rnd_nbo = 0;
1301 int reserved, dont_fragment, more_fragments, fragment_offset;
1302 unsigned short fragment;
1303
1304 // 1
1305 dest[counter] = ip -> tos;
1306 counter++;
1307 ip_hdr_profile->tos_count++;
1308
1309 // 2
1310 dest[counter] = ip -> ttl;
1311 counter++;
1312 ip_hdr_profile->ttl_count++;
1313
1314 // 3
1315 memcpy(&dest[counter], &ip->id, 2);
1316 counter += 2;
1317
1318 // 4
1319 fragment = ntohs(ip->frag_off);
1320
1321 reserved = (fragment >> 15);
1322 dont_fragment = (fragment >> 14) & 1;
1323 more_fragments = (fragment >> 13) & 1;
1324 fragment_offset = fragment & ((1<<14)-1);
1325 if(reserved != 0 || more_fragments != 0 || fragment_offset != 0) {
1326 rohc_debugf(0,"Fragment error (%d, %d, %d, %d)\n", reserved, dont_fragment, more_fragments, fragment_offset);
1327 return -1;
1328 }
1329 df_rnd_nbo = (dont_fragment << 7);
1330 ip_hdr_profile->df_count++;
1331 // Check random flags and network byte order flag in the context struct
1332 if(*rnd){
1333 df_rnd_nbo |= 0x40;
1334 }
1335 if(*nbo){
1336 df_rnd_nbo |= 0x20;
1337 }
1338 ip_hdr_profile->rnd_count++;
1339 ip_hdr_profile->nbo_count++;
1340 dest[counter] = df_rnd_nbo;
1341 counter++;
1342
1343 // 5 is not supported
1344
1345 return counter;
1346 }
1347
1348 /*
1349 Dynamic part of udp_lite header (5.7.7.5):
1350
1351 +---+---+---+---+---+---+---+---+
1352 1 / Checksum Coverage / 2 octets
1353 +---+---+---+---+---+---+---+---+
1354 2 / Checksum / 2 octets
1355 +---+---+---+---+---+---+---+---+
1356 3 | SN | 2 octets
1357 +---+---+---+---+---+---+---+---+
1358 */
1359 int udp_lite_code_dynamic_udp_part(struct sc_context *context,
1360 const struct udphdr *udp_lite,
1361 unsigned char *dest,
1362 int counter)
1363 {
1364 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
1365
1366 // 1
1367
1368 memcpy(&dest[counter], &udp_lite->len,2);
1369 counter += 2;
1370
1371
1372 // 2
1373 memcpy(&dest[counter], &udp_lite->check, 2);
1374 counter += 2;
1375
1376
1377 // 3
1378 dest[counter] = (udp_lite_profile->sn) >> 8;
1379 counter++;
1380 dest[counter] = (udp_lite_profile->sn) & 0xff;
1381 counter++;
1382 return counter;
1383 }
1384 /*
1385 Code UO0-packets according to the following pattern:
1386
1387 0 1 2 3 4 5 6 7
1388 --- --- --- --- --- --- --- ---
1389 1 : Add-CID octet :
1390 +---+---+---+---+---+---+---+---+
1391 2 | 1 1 1 1 1 0 F K | Outer packet type identifier
1392 +---+---+---+---+---+---+---+---+
1393 : :
1394 3 / 0, 1, or 2 octets of CID /
1395 : :
1396 +---+---+---+---+---+---+---+---+
1397
1398 UO-0 (5.7.1)
1399
1400 0 1 2 3 4 5 6 7
1401 +---+---+---+---+---+---+---+---+
1402 4 | 0 | SN | CRC |
1403 +===+===+===+===+===+===+===+===+
1404 */
1405
1406 int udp_lite_code_UO0_packet(struct sc_context *context,
1407 const struct iphdr *ip,
1408 unsigned char *dest,
1409 int counter,
1410 int first_position)
1411 {
1412 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
1413 unsigned char f_byte;
1414
1415
1416 int ch_sum;
1417
1418
1419 // 4
1420 f_byte = (udp_lite_profile -> sn) & 0xf;
1421 f_byte = f_byte << 3;
1422 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr == 1)
1423 ch_sum= crc_calculate(CRC_TYPE_3,(unsigned char *)ip,sizeof(struct iphdr)+sizeof(struct udphdr));
1424 else
1425 ch_sum= crc_calculate(CRC_TYPE_3,(unsigned char *)ip,2*sizeof(struct iphdr)+sizeof(struct udphdr));
1426 f_byte = f_byte + ch_sum;
1427 dest[first_position] = f_byte;
1428 return counter;
1429 }
1430
1431 /*
1432 Code UO1-packets acording to the following pattern:
1433
1434 0 1 2 3 4 5 6 7
1435 --- --- --- --- --- --- --- ---
1436 1 : Add-CID octet :
1437 +---+---+---+---+---+---+---+---+
1438 2 | first octet of base header |
1439 +---+---+---+---+---+---+---+---+
1440 : :
1441 3 / 0, 1, or 2 octets of CID /
1442 : :
1443 +---+---+---+---+---+---+---+---+
1444
1445 OU-1 (5.11.3)
1446
1447 0 1 2 3 4 5 6 7
1448 +---+---+---+---+---+---+---+---+
1449 2 | 1 0 | IP-ID |
1450 +===+===+===+===+===+===+===+===+
1451 4 | SN | CRC |
1452 +---+---+---+---+---+---+---+---+
1453
1454 */
1455 int udp_lite_code_UO1_packet(struct sc_context *context,
1456 const struct iphdr *ip,
1457 unsigned char *dest,
1458 int counter,
1459 int first_position)
1460 {
1461 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
1462 unsigned char f_byte;
1463 unsigned char s_byte;
1464
1465 int ch_sum;
1466
1467 f_byte = (udp_lite_profile -> ip_flags.id_delta) & 0x3f;
1468 f_byte |= 0x80;
1469 // Add the 5 bits of sn
1470 s_byte = (udp_lite_profile -> sn) & 0x1f;
1471 s_byte = s_byte << 3;
1472 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr == 1)
1473 ch_sum= crc_calculate(CRC_TYPE_3,(unsigned char *)ip,sizeof(struct iphdr)+sizeof(struct udphdr));
1474 else
1475 ch_sum= crc_calculate(CRC_TYPE_3,(unsigned char *)ip,2*sizeof(struct iphdr)+sizeof(struct udphdr));
1476 s_byte |= ch_sum;
1477 dest[first_position] = f_byte;
1478 dest[counter] = s_byte;
1479 counter++;
1480 return counter;
1481 }
1482
1483 /*
1484 Code UO0-packets acording to the following pattern:
1485
1486 0 1 2 3 4 5 6 7
1487 --- --- --- --- --- --- --- ---
1488 1 : Add-CID octet :
1489 +---+---+---+---+---+---+---+---+
1490 2 | first octet of base header |
1491 +---+---+---+---+---+---+---+---+
1492 : :
1493 3 / 0, 1, or 2 octets of CID /
1494 : :
1495 +---+---+---+---+---+---+---+---+
1496
1497 OU-2 (5.11.3):
1498
1499 0 1 2 3 4 5 6 7
1500 +---+---+---+---+---+---+---+---+
1501 2 | 1 1 0 | SN |
1502 +===+===+===+===+===+===+===+===+
1503 4 | X | CRC |
1504 +---+---+---+---+---+---+---+---+
1505
1506 +---+---+---+---+---+---+---+---+
1507 : :
1508 5 / Extension /
1509 : :
1510 --- --- --- --- --- --- --- ---
1511 */
1512 int udp_lite_code_UO2_packet(struct sc_context *context,
1513 struct sc_udp_lite_context *udp_lite_profile,
1514 const struct iphdr *ip,
1515 const struct iphdr *ip2,
1516 unsigned char *dest,
1517 int counter,
1518 int first_position)
1519 {
1520
1521 unsigned char f_byte;
1522 unsigned char s_byte;
1523 int ch_sum;
1524 int extension;
1525
1526 // 2
1527 f_byte = 0xc0;
1528 // Add the 4 bits of sn
1529
1530 // 4
1531 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr == 1)
1532 ch_sum= crc_calculate(CRC_TYPE_7,(unsigned char *)ip,sizeof(struct iphdr)+sizeof(struct udphdr));
1533 else
1534 ch_sum= crc_calculate(CRC_TYPE_7,(unsigned char *)ip,2*sizeof(struct iphdr)+sizeof(struct udphdr));
1535 s_byte = ch_sum;
1536
1537 // 5
1538 extension = udp_lite_decide_extension(context);
1539 if(extension == c_NOEXT){
1540 rohc_debugf(1,"code_OU2_packet(): no extension\n");
1541 // 2
1542 f_byte |= ((udp_lite_profile -> sn) & 0x1f);
1543 dest[first_position] = f_byte;
1544 // 4
1545 dest[counter] = s_byte;
1546 counter++;
1547 return counter;
1548 }
1549 // 4
1550 //We have a extension
1551 s_byte |= 0x80;
1552 dest[counter] = s_byte;
1553 counter++;
1554
1555 // 5
1556 if(extension == c_EXT0) {
1557 rohc_debugf(1,"code_OU2_packet(): using extension 0\n");
1558 // 2
1559 f_byte |= ((udp_lite_profile -> sn & 0xff) >> 3);
1560 dest[first_position] = f_byte;
1561 // 5
1562 counter = udp_lite_code_EXT0_packet(context,ip,dest,counter);
1563 } else if(extension == c_EXT1) {
1564 rohc_debugf(1,"code_OU2_packet(): using extension 1\n");
1565 // 2
1566 f_byte |= ((udp_lite_profile -> sn & 0xff) >> 3);
1567 dest[first_position] = f_byte;
1568 // 5
1569 counter = udp_lite_code_EXT1_packet(context,ip,dest,counter);
1570 } else if(extension == c_EXT2){
1571 rohc_debugf(1,"code_OU2_packet(): using extension 2\n");
1572 // 2
1573 f_byte |= ((udp_lite_profile -> sn & 0xff) >> 3);
1574 dest[first_position] = f_byte;
1575 // 5
1576 counter = udp_lite_code_EXT2_packet(context,udp_lite_profile,ip,dest,counter);
1577 }
1578 else if(extension == c_EXT3) {
1579 rohc_debugf(1,"code_OU2_packet(): using extension 3\n");
1580 // 2
1581 // check if s-field needs to be used
1582 if(udp_lite_profile->tmp_variables.nr_sn_bits > 5)
1583 f_byte |= ((udp_lite_profile -> sn) >> 8);
1584 else
1585 f_byte |= (udp_lite_profile -> sn & 0x1f);
1586
1587 dest[first_position] = f_byte;
1588 // 5
1589 counter = udp_lite_code_EXT3_packet(context,udp_lite_profile,ip,ip2,dest,counter);
1590 } else {
1591 rohc_debugf(0,"code_OU2_packet(): Unknown extension (%d)..\n", extension);
1592
1593 }
1594 return counter;
1595 }
1596
1597
1598 /*
1599 Coding the extension 0 part of the uo0-packet
1600
1601 Extension 0 (5.11.4):
1602
1603 +---+---+---+---+---+---+---+---+
1604 1 | 0 0 | SN | IP-ID |
1605 +---+---+---+---+---+---+---+---+
1606
1607 */
1608 int udp_lite_code_EXT0_packet(struct sc_context *context,const struct iphdr *ip,
1609 unsigned char *dest, int counter)
1610 {
1611 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
1612 unsigned char f_byte;
1613
1614 // 1
1615 f_byte = (udp_lite_profile -> sn) & 0x07;
1616 f_byte = f_byte << 3;
1617 f_byte |= (udp_lite_profile ->ip_flags. id_delta) & 0x07;
1618 dest[counter] = f_byte;
1619 counter++;
1620 return counter;
1621
1622 }
1623 /*
1624 Coding the extension 1 part of the uo1-packet
1625
1626 Extension 1 (5.11.4):
1627
1628 +---+---+---+---+---+---+---+---+
1629 1 | 0 1 | SN | IP-ID |
1630 +---+---+---+---+---+---+---+---+
1631 2 | IP-ID |
1632 +---+---+---+---+---+---+---+---+
1633 */
1634 int udp_lite_code_EXT1_packet(struct sc_context *context,
1635 const struct iphdr *ip,
1636 unsigned char *dest,
1637 int counter)
1638 {
1639 //Code for the extension
1640 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
1641 unsigned char f_byte;
1642 unsigned char s_byte;
1643 unsigned short id;
1644
1645 // 1
1646 f_byte = (udp_lite_profile -> sn) & 0x07;
1647 f_byte = f_byte << 3;
1648 id = (udp_lite_profile ->ip_flags. id_delta) & 0x0700;
1649 id = id >> 8;
1650 f_byte |= id;
1651 f_byte |= 0x40;
1652
1653 // 2
1654 s_byte = (udp_lite_profile ->ip_flags. id_delta) & 0xff;
1655 dest[counter] = f_byte;
1656 counter++;
1657 dest[counter] = s_byte;
1658 counter++;
1659 return counter;
1660 }
1661
1662
1663 /*
1664 Coding the extension 1 part of the uo1-packet
1665
1666 Extension 2 (5.11.4):
1667
1668 +---+---+---+---+---+---+---+---+
1669 1 | 1 0 | SN | IP-ID2 |
1670 +---+---+---+---+---+---+---+---+
1671 2 | IP-ID2 |
1672 +---+---+---+---+---+---+---+---+
1673 3 | IP-ID |
1674 +---+---+---+---+---+---+---+---+
1675
1676 IP-ID2: For outer IP-ID field.
1677 */
1678 int udp_lite_code_EXT2_packet(struct sc_context *context,
1679 struct sc_udp_lite_context *udp_lite_profile,
1680 const struct iphdr *ip,
1681 unsigned char *dest,
1682 int counter)
1683 {
1684 //Code for the extension
1685
1686 unsigned char f_byte;
1687 unsigned char s_byte;
1688 unsigned short id;
1689
1690 //its a bit confusing here but ip-id2 in the packet
1691 //description means the first headers ip-id and ip-flags
1692 //mean the first header and ip2-flags means the second
1693 //ip-header
1694 // 1
1695 f_byte = (udp_lite_profile -> sn) & 0x07;
1696 f_byte = f_byte << 3;
1697 id = (udp_lite_profile->ip_flags.id_delta) & 0x0700;
1698 id = id >> 8;
1699 f_byte |= id;
1700 f_byte |= 0x80;
1701 dest[counter] = f_byte;
1702 counter++;
1703
1704 // 2
1705 s_byte = (udp_lite_profile->ip_flags .id_delta) & 0xff;
1706 dest[counter] = s_byte;
1707 counter++;
1708
1709 // 3
1710 dest[counter] = (udp_lite_profile ->ip2_flags.id_delta) & 0xff;
1711 counter++;
1712 return counter;
1713 }
1714
1715 /*
1716 Coding the extension 3 part of the uo2-packet
1717
1718 Extension 3 (5.7.5 && 5.11.4):
1719
1720 0 1 2 3 4 5 6 7
1721 +-----+-----+-----+-----+-----+-----+-----+-----+
1722 1 | 1 1 | S | Mode | I | ip | ip2 |
1723 +-----+-----+-----+-----+-----+-----+-----+-----+
1724 2 | Inner IP header flags | | if ip = 1
1725 +-----+-----+-----+-----+-----+-----+-----+-----+
1726 3 | Outer IP header flags |
1727 +-----+-----+-----+-----+-----+-----+-----+-----+
1728 4 | SN | if S = 1
1729 +-----+-----+-----+-----+-----+-----+-----+-----+
1730 | |
1731 5 / Inner IP header fields / variable,
1732 | |
1733 +-----+-----+-----+-----+-----+-----+-----+-----+
1734 6 | IP-ID | 2 octets, if I = 1
1735 +-----+-----+-----+-----+-----+-----+-----+-----+
1736 | |
1737 7 / Outer IP header fields / variable,
1738 | |
1739 +-----+-----+-----+-----+-----+-----+-----+-----+
1740
1741 */
1742 int udp_lite_code_EXT3_packet(struct sc_context *context,
1743 struct sc_udp_lite_context *udp_lite_profile,
1744 const struct iphdr *ip,
1745 const struct iphdr *ip2,
1746 unsigned char *dest,
1747 int counter)
1748 {
1749 //Code for the extension
1750 unsigned char f_byte;
1751 unsigned char changed_fields = udp_lite_profile->tmp_variables.changed_fields;
1752 unsigned char changed_fields2 = udp_lite_profile->tmp_variables.changed_fields2;
1753 int nr_ip_id_bits = udp_lite_profile->tmp_variables.nr_ip_id_bits;
1754 int nr_ip_id_bits2 = udp_lite_profile->tmp_variables.nr_ip_id_bits2;
1755 boolean have_inner = 0;
1756 boolean have_outer = 0;
1757
1758 // 1
1759 f_byte = 0xc0;
1760 if(udp_lite_profile->tmp_variables.nr_sn_bits > 5){
1761 f_byte |= 0x20;
1762 }
1763
1764 f_byte = f_byte | (context -> c_mode) << 3;
1765 //If random bit is set we have the ip-id field outside this function
1766 rohc_debugf(1,"rnd_count_up: %d \n",udp_lite_profile->ip_flags.rnd_count);
1767
1768
1769 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1770 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr == 1){
1771 if ((nr_ip_id_bits > 0 && (context->rnd == 0))||(udp_lite_profile->ip_flags.rnd_count < MAX_FO_COUNT && context->rnd == 0)){
1772 f_byte = f_byte | 0x04;
1773 }
1774 if(udp_lite_changed_dynamic_one_hdr(changed_fields,&udp_lite_profile->ip_flags,ip,context->rnd,context->nbo,context) ||
1775 udp_lite_changed_static_one_hdr(changed_fields,&udp_lite_profile->ip_flags,ip,context))
1776 {
1777 have_inner = 1;
1778 f_byte = f_byte | 0x02;
1779 }
1780 }
1781 else{
1782 if ((nr_ip_id_bits > 0 && (context->rnd2 == 0))||(udp_lite_profile->ip2_flags.rnd_count < MAX_FO_COUNT && context->rnd2 == 0)){
1783 f_byte = f_byte | 0x04;
1784
1785 }
1786 if(udp_lite_changed_dynamic_one_hdr(changed_fields,&udp_lite_profile->ip_flags,ip,context->rnd,context->nbo,context) ||
1787 udp_lite_changed_static_one_hdr(changed_fields,&udp_lite_profile->ip_flags,ip,context))
1788 {
1789 have_outer = 1;
1790 f_byte = f_byte | 0x01;
1791 }
1792 if(udp_lite_changed_dynamic_one_hdr(changed_fields2,&udp_lite_profile->ip2_flags,ip2,context->rnd2,context->nbo2,context) ||
1793 udp_lite_changed_static_one_hdr(changed_fields2,&udp_lite_profile->ip2_flags,ip2,context))
1794 {
1795 have_inner = 1;
1796 f_byte = f_byte | 0x02;
1797 }
1798
1799 }
1800 dest[counter] = f_byte;
1801 counter++;
1802
1803
1804 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr == 1){
1805 // 2
1806 if(have_inner){
1807 counter = udp_lite_header_flags(context,changed_fields,&udp_lite_profile->ip_flags,counter,0,
1808 nr_ip_id_bits,ip,dest,context->rnd,context->nbo);
1809 }
1810 // 4
1811 if(udp_lite_profile->tmp_variables.nr_sn_bits > 5){
1812 dest[counter] = (udp_lite_profile -> sn) & 0xff;
1813 counter++;
1814 }
1815 // 5
1816 if(have_inner){
1817 counter = udp_lite_header_fields(context,changed_fields,&udp_lite_profile->ip_flags,counter,0,
1818 nr_ip_id_bits,ip,dest,context->rnd);
1819 }
1820 //6
1821 if(((nr_ip_id_bits > 0) && (context->rnd == 0)) || ((udp_lite_profile->ip_flags.rnd_count-1 < MAX_FO_COUNT) && (context->rnd == 0))){
1822
1823 memcpy(&dest[counter], &ip->id, 2);
1824 counter+=2;
1825 }
1826 }
1827 else{
1828 // 2
1829 if(have_inner){
1830 counter = udp_lite_header_flags(context,changed_fields2,&udp_lite_profile->ip2_flags,counter,0,
1831 nr_ip_id_bits2,ip2,dest,context->rnd2,context->nbo2);
1832 }
1833 // 3
1834 if(have_outer){
1835 counter = udp_lite_header_flags(context,changed_fields,&udp_lite_profile->ip_flags,counter,1,
1836 nr_ip_id_bits,ip,dest,context->rnd,context->nbo);
1837
1838 }
1839 // 4
1840 if(udp_lite_profile->tmp_variables.nr_sn_bits > 5){
1841 dest[counter] = (udp_lite_profile -> sn) & 0xff;
1842 counter++;
1843 }
1844 // 5
1845 if(have_inner){
1846 counter = udp_lite_header_fields(context,changed_fields2,&udp_lite_profile->ip2_flags,counter,0,
1847 nr_ip_id_bits2,ip2,dest,context->rnd2);
1848 }
1849 //6
1850 if(((nr_ip_id_bits2 > 0) && (context->rnd2 == 0)) || ((udp_lite_profile->ip2_flags.rnd_count-1 < MAX_FO_COUNT) && (context->rnd2 == 0))){
1851
1852 memcpy(&dest[counter], &ip2->id, 2);
1853 counter+=2;
1854 }
1855
1856 // 7
1857 if(have_outer){
1858 counter = udp_lite_header_fields(context,changed_fields,&udp_lite_profile->ip_flags,counter,1,
1859 nr_ip_id_bits,ip,dest,context->rnd);
1860 }
1861 }
1862 //No ip extension until list compression
1863 return counter;
1864 //////////////////////////////////////////////////////////////////////////////////////////////////////
1865 }
1866
1867 /*
1868 Function coding header flags:
1869
1870 For inner flags:
1871
1872 +-----+-----+-----+-----+-----+-----+-----+-----+
1873 1 | Inner IP header flags | | if ip = 1
1874 | TOS | TTL | DF | PR | IPX | NBO | RND | 0** | 0** reserved
1875 +-----+-----+-----+-----+-----+-----+-----+-----+
1876
1877
1878 or for outer flags:
1879
1880 +-----+-----+-----+-----+-----+-----+-----+-----+
1881 2 | Outer IP header flags |
1882 | TOS2| TTL2| DF2 | PR2 |IPX2 |NBO2 |RND2 | I2 | if ip2 = 1
1883 +-----+-----+-----+-----+-----+-----+-----+-----+
1884 */
1885 int udp_lite_header_flags(struct sc_context *context,
1886 unsigned short changed_fields,
1887 struct sc_udp_lite_header *ip_hdr_profile,
1888 int counter,
1889 boolean is_outer,
1890 int nr_ip_id_bits,
1891 const struct iphdr *ip,
1892 unsigned char *dest,
1893 int context_rnd,
1894 int context_nbo)
1895 {
1896 int ip_h_f = 0;
1897
1898 // 1 and 2
1899 if(udp_lite_is_changed(changed_fields,MOD_TOS) || (ip_hdr_profile->tos_count < MAX_FO_COUNT)){
1900 ip_h_f |= 0x80;
1901 }
1902 if(udp_lite_is_changed(changed_fields,MOD_TTL) || (ip_hdr_profile->ttl_count < MAX_FO_COUNT)){
1903 ip_h_f |= 0x40;
1904 }
1905 if(udp_lite_is_changed(changed_fields,MOD_PROTOCOL) || (ip_hdr_profile->protocol_count < MAX_FO_COUNT)){
1906 ip_h_f |= 0x10;
1907 }
1908
1909 rohc_debugf(1,"DF=%d\n", GET_DF(ip->frag_off));
1910 ip_hdr_profile->df_count++;
1911 ip_h_f |= GET_DF(ip->frag_off) << 5;
1912
1913 ip_hdr_profile->nbo_count++;
1914 ip_h_f |= (context_nbo) << 2;
1915
1916 ip_hdr_profile->rnd_count++;
1917 ip_h_f |= (context_rnd) << 1;
1918
1919 // Only 2
1920 if(is_outer){
1921 if ((nr_ip_id_bits > 0 && (context_rnd == 0))||(ip_hdr_profile->rnd_count-1 < MAX_FO_COUNT && context_rnd == 0) ){
1922 ip_h_f |= 0x01;
1923
1924 }
1925 }
1926
1927
1928 // 1 and 2
1929 dest[counter] = ip_h_f;
1930 counter++;
1931
1932 return counter;
1933 }
1934
1935 /*
1936 Function coding header fields:
1937
1938 For inner fields and outer fields (The function is called two times
1939 one for inner and one for outer with different arguments):
1940
1941 +-----+-----+-----+-----+-----+-----+-----+-----+
1942 1 | Type of Service/Traffic Class | if TOS = 1
1943 ..... ..... ..... ..... ..... ..... ..... .....
1944 2 | Time to Live/Hop Limit | if TTL = 1
1945 ..... ..... ..... ..... ..... ..... ..... .....
1946 3 | Protocol/Next Header | if PR = 1
1947 ..... ..... ..... ..... ..... ..... ..... .....
1948 4 / IP extension headers / variable, if IPX = 1
1949 ..... ..... ..... ..... ..... ..... ..... .....
1950
1951 Ip id is coded here for both inner and outer fields though it doesn't look that way
1952 in the extension 3 picture in 5.7.5 and 5.11.4 of rfc 3095
1953 +-----+-----+-----+-----+-----+-----+-----+-----+
1954 5 | IP-ID | 2 octets, if I = 1
1955 +-----+-----+-----+-----+-----+-----+-----+-----+
1956
1957 4 is not supported.
1958
1959 */
1960 int udp_lite_header_fields(struct sc_context *context,
1961 unsigned short changed_fields,
1962 struct sc_udp_lite_header *ip_hdr_profile,
1963 int counter,
1964 boolean is_outer,
1965 int nr_ip_id_bits,
1966 const struct iphdr *ip,
1967 unsigned char *dest,
1968 int context_rnd)
1969 {
1970 // 1
1971 if(udp_lite_is_changed(changed_fields,MOD_TOS) || (ip_hdr_profile->tos_count < MAX_FO_COUNT)){
1972 ip_hdr_profile->tos_count++;
1973 dest[counter] = ip->tos;
1974 counter++;
1975 }
1976
1977 // 2
1978 if(udp_lite_is_changed(changed_fields,MOD_TTL) || (ip_hdr_profile->ttl_count < MAX_FO_COUNT)){
1979 ip_hdr_profile->ttl_count++;
1980 dest[counter] = ip->ttl;
1981 counter++;
1982 }
1983
1984 // 3
1985 if(udp_lite_is_changed(changed_fields,MOD_PROTOCOL) || (ip_hdr_profile->protocol_count < MAX_FO_COUNT) ){
1986 ip_hdr_profile->protocol_count++;
1987 dest[counter] = ip->protocol;
1988 counter++;
1989 }
1990
1991 // 5
1992 if(is_outer){
1993 if(((nr_ip_id_bits > 0) && (context_rnd == 0)) || ((ip_hdr_profile->rnd_count-1 < MAX_FO_COUNT) && (context_rnd == 0))){
1994
1995 memcpy(&dest[counter], &ip->id, 2);
1996 counter+=2;
1997
1998 }
1999 }
2000
2001
2002 return counter;
2003 }
2004
2005
2006
2007 /*Decide what extension shall be used in the uo2 packet*/
2008 int udp_lite_decide_extension(struct sc_context *context)
2009 {
2010 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
2011 int nr_ip_id_bits = udp_lite_profile->tmp_variables.nr_ip_id_bits;
2012 int nr_ip_id_bits2 = udp_lite_profile->tmp_variables.nr_ip_id_bits2;
2013 int nr_sn_bits = udp_lite_profile->tmp_variables.nr_sn_bits;
2014 //if (ip_context->ttl_count < MAX_FO_COUNT || ip_context->tos_count < MAX_FO_COUNT || ip_context->df_count < MAX_FO_COUNT)
2015 // return c_EXT3;
2016
2017 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr == 1){
2018 if(udp_lite_profile->tmp_variables.send_static > 0){
2019 rohc_debugf(2,"Vi har ändrat static\n");
2020 return c_EXT3;
2021
2022 }
2023 if(udp_lite_profile->tmp_variables.send_dynamic > 0){
2024 return c_EXT3;
2025 }
2026 if(nr_sn_bits < 5 && (nr_ip_id_bits == 0 || context->rnd == 1)){
2027 return c_NOEXT;
2028 }
2029 else if(nr_sn_bits <= 8 && nr_ip_id_bits <= 3){
2030 return c_EXT0;
2031 }
2032 else if(nr_sn_bits <= 8 && nr_ip_id_bits <= 11){
2033 return c_EXT1;
2034 }
2035 else{
2036 return c_EXT3;
2037 }
2038 }
2039 else{
2040 if(udp_lite_profile->tmp_variables.send_static > 0 || udp_lite_profile->tmp_variables.send_dynamic > 0){
2041 return c_EXT3;
2042
2043 }
2044 if(nr_sn_bits < 5 && (nr_ip_id_bits == 0 || context->rnd == 1)
2045 && (nr_ip_id_bits2 == 0 || context->rnd2 == 1)){
2046 return c_NOEXT;
2047 }
2048 else if(nr_sn_bits <= 8 && nr_ip_id_bits <= 3
2049 && (nr_ip_id_bits2 == 0 || context->rnd2 == 1)){
2050 return c_EXT0;
2051 }
2052 else if(nr_sn_bits <= 8 && nr_ip_id_bits <= 11
2053 && (nr_ip_id_bits2 == 0 || context->rnd2 == 1)){
2054 return c_EXT1;
2055 }
2056 else if(nr_sn_bits <= 3 && nr_ip_id_bits <= 11
2057 && nr_ip_id_bits2 <= 8){
2058 return c_EXT2;
2059 }
2060
2061 else{
2062 return c_EXT3;
2063 }
2064 }
2065
2066 }
2067 /*
2068 Check if the static part of the context has been changed in any of the two first headers
2069 */
2070 int udp_lite_changed_static_both_hdr(struct sc_context *context,
2071 const struct iphdr *ip,
2072 const struct iphdr *ip2)
2073 {
2074 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
2075 unsigned char changed_fields = udp_lite_profile->tmp_variables.changed_fields;
2076 unsigned char changed_fields2 = udp_lite_profile->tmp_variables.changed_fields2;
2077 int return_value = 0;
2078
2079
2080 return_value = udp_lite_changed_static_one_hdr(changed_fields,&udp_lite_profile->ip_flags,ip,context);
2081 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
2082 return_value += udp_lite_changed_static_one_hdr(changed_fields2,&udp_lite_profile->ip2_flags,ip2,context);
2083 }
2084 return return_value;
2085 }
2086
2087 /*
2088 Check if the static part of the context has been changed in one of header
2089 */
2090 int udp_lite_changed_static_one_hdr(unsigned short udp_lite_changed_fields,
2091 struct sc_udp_lite_header *ip_header,
2092 const struct iphdr *ip,
2093 struct sc_context *context)
2094 {
2095 int return_value = 0;
2096 struct sc_udp_lite_context *org_udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
2097
2098 if (udp_lite_is_changed(udp_lite_changed_fields,MOD_PROTOCOL) || (ip_header->protocol_count < MAX_FO_COUNT)){
2099 rohc_debugf(2,"protocol_count %d\n",ip_header->protocol_count);
2100 if (udp_lite_is_changed(udp_lite_changed_fields,MOD_PROTOCOL)) {
2101 ip_header->protocol_count = 0;
2102 org_udp_lite_profile->fo_count = 0;
2103 }
2104
2105
2106 return_value += 1;
2107 }
2108 return return_value;
2109
2110 }
2111
2112
2113 /*
2114 Check if the dynamic parts are changed, it returns the number of
2115 dynamic bytes that are changed in both of the two first headers
2116 */
2117 int udp_lite_changed_dynamic_both_hdr(struct sc_context *context,
2118 const struct iphdr *ip,
2119 const struct iphdr *ip2)
2120 {
2121 int return_value = 0;
2122 struct sc_udp_lite_context *udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
2123 int changed_fields = udp_lite_profile->tmp_variables.changed_fields;
2124 int changed_fields2 = udp_lite_profile->tmp_variables.changed_fields2;
2125
2126 return_value = udp_lite_changed_dynamic_one_hdr(changed_fields,&udp_lite_profile->ip_flags,ip,context->rnd,context->nbo,context);
2127 //rohc_debugf(1,"return_value = %d \n",return_value);
2128 if(udp_lite_profile->tmp_variables.nr_of_ip_hdr > 1){
2129
2130 return_value += udp_lite_changed_dynamic_one_hdr(changed_fields2,&udp_lite_profile->ip2_flags,ip2,context->rnd2,context->nbo2,context);
2131 }
2132 return return_value;
2133 }
2134
2135 /*
2136 Check if the dynamic part of the context has been changed in one of header
2137 */
2138 int udp_lite_changed_dynamic_one_hdr(unsigned short udp_lite_changed_fields,
2139 struct sc_udp_lite_header *ip_hdr_profile,
2140 const struct iphdr *ip,
2141 int context_rnd,
2142 int context_nbo,
2143 struct sc_context *context)
2144 {
2145 int return_value = 0;
2146 int small_flags = 0;
2147 struct sc_udp_lite_context *org_udp_lite_profile = (struct sc_udp_lite_context *)context->profile_context;
2148
2149 if (udp_lite_is_changed(udp_lite_changed_fields,MOD_TOS) || (ip_hdr_profile->tos_count < MAX_FO_COUNT)){
2150
2151 if (udp_lite_is_changed(udp_lite_changed_fields,MOD_TOS)){
2152 ip_hdr_profile->tos_count = 0;
2153 org_udp_lite_profile->fo_count = 0;
2154 }
2155
2156 return_value += 1;
2157 }
2158 if(udp_lite_is_changed(udp_lite_changed_fields,MOD_TTL) || (ip_hdr_profile->ttl_count < MAX_FO_COUNT)){
2159 if (udp_lite_is_changed(udp_lite_changed_fields,MOD_TTL)){
2160 ip_hdr_profile->ttl_count = 0;
2161 org_udp_lite_profile->fo_count = 0;
2162 }
2163
2164 return_value += 1;
2165 }
2166 /*if(udp_lite_is_changed(udp_lite_changed_fields,MOD_FRAG_OFF)){
2167 udp_lite_profile->df_count = 0;
2168 return_value += 1;
2169 }*/
2170 if((GET_DF(ip->frag_off) != GET_DF(ip_hdr_profile->old_ip.frag_off)) || (ip_hdr_profile->df_count < MAX_FO_COUNT)){
2171 if (GET_DF(ip->frag_off) != GET_DF(ip_hdr_profile->old_ip.frag_off)){
2172 ip_hdr_profile->ttl_count = 0;
2173 org_udp_lite_profile->fo_count = 0;
2174 }
2175 return_value += 1;
2176 }
2177
2178 rohc_debugf(2,"rnd_count=%d nbo_count=%d\n", ip_hdr_profile->rnd_count, ip_hdr_profile->nbo_count);
2179 if(context_rnd != ip_hdr_profile->old_rnd || ip_hdr_profile->rnd_count < MAX_FO_COUNT){
2180
2181 if (context_rnd != ip_hdr_profile->old_rnd) {
2182 rohc_debugf(1,"RND changed, reseting count..\n");
2183 ip_hdr_profile->rnd_count = 0;
2184 org_udp_lite_profile->fo_count = 0;
2185 }
2186
2187 small_flags += 1;
2188
2189 }
2190 rohc_debugf(2,"nbo = %d, old_nbo = %d \n",context_nbo,ip_hdr_profile->old_nbo);
2191 if(context_nbo != ip_hdr_profile->old_nbo || ip_hdr_profile->nbo_count < MAX_FO_COUNT){
2192 if (context_nbo != ip_hdr_profile->old_nbo) {
2193 rohc_debugf(1,"NBO changed, reseting count..\n");
2194 ip_hdr_profile->nbo_count = 0;
2195 org_udp_lite_profile->fo_count = 0;
2196 }
2197
2198 small_flags += 1;
2199 }
2200 if(small_flags > 0) {
2201 return_value += 1;
2202 }
2203 //rohc_debugf(1,"return_value = %d \n",return_value);
2204 rohc_debugf(2,"udp_lite_changed_dynamic_both_hdr()=%d\n", return_value);
2205 return return_value;
2206
2207
2208 }
2209
2210 int udp_lite_changed_udp_dynamic(struct sc_context *context,const struct udphdr *udp_lite){
2211 return 0;
2212 }
2213
2214
2215 /*
2216 Check if a specified field is changed, it is checked against the bitfield
2217 created in the function udp_lite_changed_fields
2218 */
2219 boolean udp_lite_is_changed(unsigned short udp_lite_changed_fields,unsigned short check_field)
2220 {
2221 if((udp_lite_changed_fields & check_field) > 0)
2222 return 1;
2223 else
2224 return 0;
2225 }
2226 /*
2227 This function returns a bitpattern, the bits that are set is changed
2228 */
2229 unsigned short udp_lite_changed_fields(struct sc_udp_lite_header *ip_hdr_profile,const struct iphdr *ip)
2230 {
2231 unsigned short ret_value = 0;
2232
2233 //Kan version och header length bitordersskiftningar ha någon betydelse för oss??
2234 if(ip_hdr_profile -> old_ip.tos != ip -> tos)
2235 ret_value |= MOD_TOS;
2236 if(ip_hdr_profile -> old_ip.tot_len != ip -> tot_len)
2237 ret_value |= MOD_TOT_LEN;
2238 if(ip_hdr_profile -> old_ip.id != ip -> id)
2239 ret_value |= MOD_ID;
2240 if(ip_hdr_profile -> old_ip.frag_off != ip -> frag_off)
2241 ret_value |= MOD_FRAG_OFF;
2242 if(ip_hdr_profile -> old_ip.ttl != ip -> ttl)
2243 ret_value |= MOD_TTL;
2244 if(ip_hdr_profile -> old_ip.protocol != ip -> protocol)
2245 ret_value |= MOD_PROTOCOL;
2246 if(ip_hdr_profile -> old_ip.check != ip -> check)
2247 ret_value |= MOD_CHECK;
2248 if(ip_hdr_profile -> old_ip.saddr != ip -> saddr)
2249 ret_value |= MOD_SADDR;
2250 if(ip_hdr_profile -> old_ip.daddr != ip -> daddr)
2251 ret_value |= MOD_DADDR;
2252
2253 return ret_value;
2254 }
2255 /*
2256 Function to determine if the ip-identification has nbo and if it is random
2257 */
2258 void udp_lite_check_ip_identification(struct sc_udp_lite_header *ip_hdr_profile,
2259 const struct iphdr *ip,
2260 int *context_rnd,
2261 int *context_nbo)
2262 {
2263
2264 int id1, id2;
2265 int nbo = -1;
2266
2267 id1 = ntohs(ip_hdr_profile->old_ip.id);
2268 id2 = ntohs(ip->id);
2269
2270
2271 rohc_debugf(2,"1) id1=0x%04x id2=0x%04x\n", id1, id2);
2272
2273 if (id2-id1 < IPID_MAX_DELTA && id2-id1 > 0)
2274 {
2275 nbo = 1;
2276 } else if ((id1 + IPID_MAX_DELTA > 0xffff) && (id2 < ((id1+IPID_MAX_DELTA) & 0xffff))) {
2277 nbo = 1;
2278 }
2279
2280 if (nbo == -1) {
2281 // change byte ordering and check nbo=0
2282 id1 = (id1>>8) | ((id1<<8) & 0xff00);
2283 id2 = (id2>>8) | ((id2<<8) & 0xff00);
2284
2285 rohc_debugf(2,"2) id1=0x%04x id2=0x%04x\n", id1, id2);
2286
2287 if (id2-id1 < IPID_MAX_DELTA && id2-id1 > 0)
2288 {
2289 nbo = 0;
2290 } else if ((id1 + IPID_MAX_DELTA > 0xffff) && (id2 < ((id1+IPID_MAX_DELTA) & 0xffff))) {
2291 nbo = 0;
2292 }
2293 }
2294
2295 if (nbo == -1) {
2296 rohc_debugf(2,"check_ip_id(): RND detected!\n");
2297 *context_rnd = 1;
2298
2299 } else {
2300 rohc_debugf(2,"check_ip_id(): NBO=%d\n", nbo);
2301 *context_rnd = 0;
2302 *context_nbo = nbo;
2303 }
2304
2305 }
2306 /*Function that set up how what context the compressor and decompressor will
2307 have from the start */
2308 void udp_lite_initiate_coverage_context(struct sc_udp_lite_context *udp_lite_profile,
2309 const struct udphdr *udp_lite,
2310 unsigned char *dest,
2311 struct sc_context *context)
2312
2313 {
2314 int packet_length = udp_lite_profile->tmp_variables.udp_size; //from packet
2315 if(udp_lite_profile->ir_count == 1){
2316 udp_lite_profile->cfp = 0;
2317 udp_lite_profile->cfi = 1;
2318 }
2319
2320 rohc_debugf(2,"packet_length=%d\n", packet_length);
2321 rohc_debugf(2,"udp_lite->len=%d\n", ntohs(udp_lite->len));
2322
2323 udp_lite_profile->cfp = (ntohs(udp_lite->len) != packet_length) || udp_lite_profile->cfp;
2324 udp_lite_profile->cfi = (ntohs(udp_lite->len) == packet_length) && udp_lite_profile->cfi;
2325 rohc_debugf(2,"cfp-value=%d\n", udp_lite_profile->cfp);
2326 rohc_debugf(2,"cfi-value=%d\n", udp_lite_profile->cfi);
2327 udp_lite_profile->tmp_coverage = udp_lite->len;
2328 udp_lite_profile->old_udp_lite = *udp_lite;
2329 }
2330
2331 /*
2332 The function check if we have to send a ce-packet,
2333 OBSERVE!!!! that its also updates the FK variable in the profile structure.
2334 This have to be noticed.
2335 */
2336 boolean udp_lite_send_ce_packet(struct sc_udp_lite_context *udp_lite_profile,
2337 const struct udphdr *udp_lite,
2338 unsigned char *dest,
2339 struct sc_context *context)
2340 {
2341 boolean inferred;
2342 boolean same;
2343 int packet_length = udp_lite_profile->tmp_variables.udp_size;
2344
2345 inferred = ntohs(udp_lite->len) == packet_length;
2346 same = ntohs(udp_lite_profile->old_udp_lite.len) == ntohs(udp_lite->len);
2347 if(udp_lite_profile->sent_ce_only_count > 0)
2348 same = ntohs(udp_lite_profile->tmp_coverage) == ntohs(udp_lite->len);
2349
2350 udp_lite_profile->tmp_coverage = udp_lite->len;
2351 if(same){
2352 udp_lite_profile->coverage_equal_count++;
2353 if(inferred)
2354 udp_lite_profile->coverage_inferred_count++;
2355
2356
2357 }
2358 else{
2359 udp_lite_profile->coverage_equal_count = 0;
2360 if(inferred){
2361 udp_lite_profile->coverage_inferred_count++;
2362 }
2363 else{
2364 udp_lite_profile->coverage_inferred_count = 0;
2365 }
2366 }
2367
2368 if(udp_lite_profile->cfp == 0 && udp_lite_profile->cfi == 1){
2369 if(inferred == 0){
2370 if(udp_lite_profile->sent_ce_only_count < MAX_IR_COUNT){
2371 udp_lite_profile->sent_ce_only_count++;
2372 udp_lite_profile->FK = 0x01;
2373 return 1;
2374 }
2375 else {
2376 if(udp_lite_profile->coverage_equal_count > MAX_LITE_COUNT){
2377 udp_lite_profile->cfp = 0;
2378 udp_lite_profile->cfi = 0;
2379 udp_lite_profile->sent_ce_only_count = 0;
2380 udp_lite_profile->sent_ce_off_count = 1;
2381 udp_lite_profile->FK = 0x03;
2382 udp_lite_profile->old_udp_lite = *udp_lite;
2383 return 1;
2384 }
2385 else{
2386 udp_lite_profile->cfp = 1;
2387 udp_lite_profile->cfi = 0;
2388 udp_lite_profile->sent_ce_only_count = 0;
2389 udp_lite_profile->sent_ce_on_count = 1;
2390 udp_lite_profile->FK = 0x02;
2391 udp_lite_profile->old_udp_lite = *udp_lite;
2392 return 1;
2393 }
2394
2395 }
2396 }
2397
2398 }
2399 else if(udp_lite_profile->cfp == 0 && udp_lite_profile->cfi == 0){
2400 if(inferred || (!inferred && !same)){
2401 if(udp_lite_profile->sent_ce_only_count < MAX_IR_COUNT){
2402 udp_lite_profile->sent_ce_only_count++;
2403 udp_lite_profile->FK = 0x01;
2404 return 1;
2405 }
2406 else{
2407 if(udp_lite_profile->coverage_inferred_count > MAX_LITE_COUNT){
2408 udp_lite_profile->cfp = 0;
2409 udp_lite_profile->cfi = 1;
2410 udp_lite_profile->sent_ce_only_count = 0;
2411 udp_lite_profile->sent_ce_off_count = 1;
2412 udp_lite_profile->FK = 0x03;
2413 udp_lite_profile->old_udp_lite = *udp_lite;
2414 return 1;
2415 }
2416 else{
2417 udp_lite_profile->cfp = 1;
2418 udp_lite_profile->cfi = 0;
2419 udp_lite_profile->sent_ce_only_count = 0;
2420 udp_lite_profile->sent_ce_on_count = 1;
2421 udp_lite_profile->FK = 0x02;
2422 udp_lite_profile->old_udp_lite = *udp_lite;
2423 return 1;
2424 }
2425 }
2426 }
2427 }
2428
2429 else if(udp_lite_profile->cfp == 1){
2430 if(inferred || (inferred && same)){
2431 if(udp_lite_profile->coverage_equal_count > MAX_LITE_COUNT){
2432 udp_lite_profile->sent_ce_off_count = 1;
2433 udp_lite_profile->sent_ce_only_count = 0;
2434 udp_lite_profile->cfp = 0;
2435 udp_lite_profile->cfi = 0;
2436 udp_lite_profile->FK = 0x03;
2437 udp_lite_profile->old_udp_lite = *udp_lite;
2438 return 1;
2439 }
2440 else if(udp_lite_profile->coverage_inferred_count > MAX_LITE_COUNT){
2441 udp_lite_profile->sent_ce_off_count = 1;
2442 udp_lite_profile->sent_ce_only_count = 0;
2443 udp_lite_profile->cfp = 0;
2444 udp_lite_profile->cfi = 1;
2445 udp_lite_profile->FK = 0x03;
2446 udp_lite_profile->old_udp_lite = *udp_lite;
2447 return 1;
2448 }
2449 }
2450 }
2451
2452 if(udp_lite_profile->sent_ce_off_count < MAX_IR_COUNT){
2453 udp_lite_profile->sent_ce_off_count++;
2454 udp_lite_profile->sent_ce_only_count = 0;
2455 udp_lite_profile->FK = 0x03;
2456 udp_lite_profile->old_udp_lite = *udp_lite;
2457 return 1;
2458 }else if(udp_lite_profile->sent_ce_on_count < MAX_IR_COUNT){
2459 udp_lite_profile->sent_ce_on_count++;
2460 udp_lite_profile->sent_ce_only_count = 0;
2461 udp_lite_profile->FK = 0x02;
2462 udp_lite_profile->old_udp_lite = *udp_lite;
2463 return 1;
2464 }
2465
2466 udp_lite_profile->sent_ce_only_count = 0;
2467 return 0;
2468
2469 }
2470
2471 /*
2472 A struct thate every function must have the first fieldtell what protocol this profile has.
2473 The second row is the profile id-number, Then two strings that is for printing version and
2474 description. And finally pointers to functions that have to exist in every profile.
2475 */
2476 struct sc_profile c_udp_lite_profile = {
2477 UDP_LITE_PRNR,
2478 8, // Profile ID
2479 "1.0b", // Version
2480 "UDP-Lite / Compressor", // Description
2481 c_udp_lite_create,
2482 c_udp_lite_destroy,
2483 c_udp_lite_check_context,
2484 c_udp_lite_encode,
2485 c_udp_lite_feedback
2486 };
2487