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