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