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