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