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

File Contents

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