ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/c_udp.c
Revision: 1.3
Committed: Tue Apr 26 00:55:56 2005 UTC (19 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_01, rel-3_0, rel-2_2, rel-2_0, rel-2_21, rel-2_22, rel-2_25, HEAD
Changes since 1.2: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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