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