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