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

File Contents

# User Rev Content
1 pcg 1.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 "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