ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/c_ip.c
Revision: 1.1
Committed: Sun Feb 8 06:02:44 2004 UTC (20 years, 5 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: ROHC-IMPORT-2004-02-08
Log Message:
*** empty log message ***

File Contents

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