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, 4 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: ROHC-IMPORT-2004-02-08
Log Message:
*** empty log message ***

File Contents

# 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 <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