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

File Contents

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