ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/c_udp_lite.c
Revision: 1.2
Committed: Sun Feb 8 07:24:25 2004 UTC (20 years, 4 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_9, rel-1_8, VPE_1_6, rel-1_7, VPE-1_6_1
Changes since 1.1: +0 -2 lines
Log Message:
*** empty log message ***

File Contents

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