ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/c_uncompressed.c
Revision: 1.3
Committed: Tue Apr 26 00:55:56 2005 UTC (19 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_01, rel-3_0, rel-2_2, rel-2_0, rel-2_21, rel-2_22, rel-2_25, HEAD
Changes since 1.2: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 ROHC Project 2003 at Lulea University of Technology, Sweden.
3 Authors: Andreas Vernersson <andver-8@student.luth.se>
4 Daniel Pettersson <danpet-7@student.luth.se>
5 Erik Soderstrom <soderstrom@yahoo.com>
6 Fredrik Lindstrom <frelin-9@student.luth.se>
7 Johan Stenmark <johste-8@student.luth.se>
8 Martin Juhlin <juhlin@users.sourceforge.net>
9 Mikael Larsson <larmik-9@student.luth.se>
10 Robert Maxe <robmax-1@student.luth.se>
11
12 Copyright (C) 2003 Andreas Vernersson, Daniel Pettersson,
13 Erik Soderström, Fredrik Lindström, Johan Stenmark,
14 Martin Juhlin, Mikael Larsson, Robert Maxe.
15
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 2 of the License, or
19 (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30 /*
31 * Implementation of the uncompressed profile (compressor)
32 */
33
34 #include "rohc.h"
35 #include "comp.h"
36 #include "c_util.h"
37
38
39 /*
40 Structure that contain counters, flags and structures that need to saved between different
41 packages. Every context have one of these
42 */
43 struct sc_uncompressed_context {
44 int ir_count, normal_count;
45 int go_back_ir_count;
46
47
48 };
49
50 static void uncompressed_decide_state(struct sc_context *context);
51
52 static void uncompressed_periodic_down_transition(struct sc_context *context);
53
54 static void uncompressed_change_mode(struct sc_context *c, C_MODE new_mode);
55
56 static void uncompressed_change_state(struct sc_context *c, C_STATE new_state);
57
58 static int uncompressed_code_packet(struct sc_context *context,
59 const struct iphdr *ip,
60 unsigned char *dest,
61 int *payload_offset,
62 int max_size);
63
64 static int uncompressed_code_IR_packet(struct sc_context *context,
65 const struct iphdr *ip,
66 unsigned char *dest,
67 int *payload_offset,
68 int max_size);
69
70 static int uncompressed_code_normal_packet(struct sc_context *context,
71 const struct iphdr *ip,
72 unsigned char *dest,
73 int *payload_offset,
74 int max_size);
75
76 /*
77 Function to allocate for a new context, it aslo initilize alot of variables.
78
79 This function is one of the functions that must exist for the framework to
80 work. Please notice that a pointer to this function has to exist in the
81 sc_profile struct thatwe have in the bottom of this file.
82 */
83 int c_uncompressed_create(struct sc_context *context, const struct iphdr *ip)
84 {
85 struct sc_uncompressed_context *uncompressed_profile;
86
87 context->profile_context = kmalloc(sizeof(struct sc_uncompressed_context),GFP_ATOMIC);
88 if (context->profile_context == 0) {
89 rohc_debugf(0,"c_ip_create(): no mem for profile context\n");
90 return 0;
91 }
92 uncompressed_profile = (struct sc_uncompressed_context *)context->profile_context;
93
94 uncompressed_profile->ir_count = 0;
95 uncompressed_profile->normal_count = 0;
96
97 uncompressed_profile->go_back_ir_count = 0;
98 return 1;
99
100 }
101
102
103 /*
104 Function to deallocate a context.
105
106 This function is one of the functions that must exist for the framework to
107 work. Please notice that a pointer to this function has to exist in the
108 sc_profile struct thatwe have in the bottom of this file.
109 */
110 void c_uncompressed_destroy(struct sc_context *context){
111
112 if (context->profile_context != 0)
113 kfree(context->profile_context);
114
115 }
116
117 /*
118 A package can always be sent uncompressed
119
120 This function is one of the functions that must exist for the framework to
121 work. Please notice that a pointer to this function has to exist in the
122 sc_profile struct that we have in the bottom of this file.
123 */
124 int c_uncompressed_check_context(struct sc_context *context, const struct iphdr *ip){
125 return 1;
126 }
127
128 /*
129 Encode packages to a pattern decided by two different factors.
130 1. Decide state
131 2. Code packet
132
133 This function is one of the functions that must exist for the framework to
134 work. Please notice that a pointer to this function has to exist in the
135 sc_profile struct that we have in the bottom of this file.
136 */
137 int c_uncompressed_encode(struct sc_context *context,
138 const struct iphdr *ip,
139 int packet_size,
140 unsigned char *dest,
141 int max_size,
142 int *payload_offset)
143
144 {
145 int size;
146
147 // 1
148 uncompressed_decide_state(context);
149
150 //2
151 size = uncompressed_code_packet(context,ip,dest,payload_offset,max_size);
152
153 return size;
154 }
155
156 /*
157 Function that update the profile when feedback has arrived.
158
159 This function is one of the functions that must exist for the framework to
160 work. Please notice that a pointer to this function has to exist in the
161 sc_profile struct that we have in the bottom of this file.
162 */
163 void c_uncompressed_feedback(struct sc_context *context, struct sc_feedback *feedback)
164 {
165 //struct sc_uncompressed_context *uncompressed_context = (struct sc_uncompressed_context *)context->profile_context;
166 unsigned char *p = feedback->data + feedback->specific_offset;
167
168 if (feedback->type == 1) { // ack
169
170 } else if (feedback->type == 2) { // FEEDBACK-2
171 unsigned int crc = 0, crc_used=0;
172
173 int sn_not_valid = 0;
174 unsigned char mode = (p[0]>>4) & 3;
175 unsigned int sn = ((p[0] & 15) << 8) + p[1];
176 int remaining = feedback->specific_size-2;
177 p+=2;
178
179
180 while (remaining > 0) {
181 int opt = p[0]>>4;
182 int optlen = p[0] & 0x0f;
183
184 switch (opt) {
185 case 1: // CRC
186 crc = p[1];
187 crc_used = 1;
188 p[1] = 0; // set to zero for crc computation..
189 break;
190 //case 2: // Reject
191 //break;
192 case 3: // SN-Not-Valid
193 sn_not_valid=1;
194 break;
195 case 4: // SN -- TODO: how is several SN options combined?
196 sn = (sn<<8) + p[1];
197 break;
198 //case 7: // Loss
199 //break;
200 default:
201 rohc_debugf(0,"c_ip_feedback(): Unknown feedback type: %d\n", opt);
202 break;
203 }
204
205 remaining -= 1 + optlen;
206 p += 1 + optlen;
207 }
208
209 if (crc_used) { // check crc..
210 if (crc_calculate(CRC_TYPE_8, feedback->data, feedback->size ) != crc) {
211 rohc_debugf(0,"c_ip_feedback(): crc check failed..(size=%d)\n", feedback->size);
212 return;
213 }
214 }
215
216 if (mode != 0) {
217 if (crc_used) {
218 uncompressed_change_mode(context, mode);
219 rohc_debugf(1,"c_ip_feedback(): changing mode to %d\n", mode);
220 } else {
221 rohc_debugf(0,"c_ip_feedback(): mode change requested but no crc was given..\n");
222 }
223 }
224
225 switch (feedback->acktype) {
226 case ACK:
227
228 break;
229
230 case NACK:
231
232
233 break;
234
235 case STATIC_NACK:
236 uncompressed_change_state(context, IR);
237 break;
238
239 case RESERVED:
240 rohc_debugf(0, "c_ip_feedback(): reserved field used\n");
241 break;
242 }
243
244 } else {
245 rohc_debugf(0,"c_ip_feedback(): Feedback type not implemented (%d)\n", feedback->type);
246 }
247
248 }
249
250 /* Decide the state we will work in. Observe that RFC3095 defines the states as ir and normal, but here
251 we call normal state FO instead*/
252 void uncompressed_decide_state(struct sc_context *context)
253 {
254 struct sc_uncompressed_context *uncompressed_profile = (struct sc_uncompressed_context *)context->profile_context;
255
256 if(context->c_state == IR && uncompressed_profile->ir_count >= MAX_IR_COUNT){
257 uncompressed_change_state(context, FO);
258 }
259 if(context->c_mode == U){
260 uncompressed_periodic_down_transition(context);
261 }
262 }
263
264 /*Function that change state periodicly after a certain number of packets */
265 void uncompressed_periodic_down_transition(struct sc_context *context)
266 {
267 struct sc_uncompressed_context *uncompressed_profile = (struct sc_uncompressed_context *)context->profile_context;
268 if(uncompressed_profile->go_back_ir_count == CHANGE_TO_IR_COUNT){
269 uncompressed_profile->go_back_ir_count = 0;
270 uncompressed_change_state(context, IR);
271 }
272 if (context->c_state == FO)
273 uncompressed_profile->go_back_ir_count++;
274
275 }
276
277 // Change the mode of this context
278 void uncompressed_change_mode(struct sc_context *c, C_MODE new_mode) {
279 if(c->c_mode != new_mode){
280 c->c_mode = new_mode;
281 uncompressed_change_state(c, IR);
282 }
283 }
284
285 // Change the state of this context
286 void uncompressed_change_state(struct sc_context *context, C_STATE new_state)
287 {
288
289 struct sc_uncompressed_context *uncompressed_profile = (struct sc_uncompressed_context *)context->profile_context;
290 // Reset counters only if different state
291 if (context->c_state != new_state) {
292 uncompressed_profile->ir_count = 0;
293 uncompressed_profile->normal_count = 0;
294
295 }
296
297 context->c_state = new_state;
298 }
299
300 /*
301 Code the packet, it is eiter IR or normal
302 */
303 int uncompressed_code_packet(struct sc_context *context,
304 const struct iphdr *ip,
305 unsigned char *dest,
306 int *payload_offset,
307 int max_size){
308
309 struct sc_uncompressed_context *uncompressed_profile = (struct sc_uncompressed_context *)context->profile_context;
310 switch(context->c_state){
311 case IR:
312 rohc_debugf(1,"uncompressed_code_packet(): IR packet uncomp..\n");
313 uncompressed_profile->ir_count++;
314 return uncompressed_code_IR_packet(context,ip,dest,payload_offset,max_size);
315 break;
316 case FO:
317 rohc_debugf(1,"uncompressed_code_packet(): normal packet uncomp..\n");
318 uncompressed_profile->normal_count++;
319 return uncompressed_code_normal_packet(context,ip,dest,payload_offset,max_size);
320 break;
321 default:
322 rohc_debugf(0,"uncompressed_code_packet(): Unknown packet..\n");
323 return -1;
324 }
325 }
326 /*
327
328 IR packet (5.10.1)
329
330 0 1 2 3 4 5 6 7
331 --- --- --- --- --- --- --- ---
332 1 : Add-CID octet : if for small CIDs and (CID != 0)
333 +---+---+---+---+---+---+---+---+
334 2 | 1 1 1 1 1 1 0 |res|
335 +---+---+---+---+---+---+---+---+
336 : :
337 3 / 0-2 octets of CID info / 1-2 octets if for large CIDs
338 : :
339 +---+---+---+---+---+---+---+---+
340 4 | Profile = 0 | 1 octet
341 +---+---+---+---+---+---+---+---+
342 5 | CRC | 1 octet
343 +---+---+---+---+---+---+---+---+
344 : : (optional)
345 / IP packet / variable length
346 : :
347 --- --- --- --- --- --- --- ---
348
349 */
350 int uncompressed_code_IR_packet(struct sc_context *context,
351 const struct iphdr *ip,
352 unsigned char *dest,
353 int *payload_offset,
354 int max_size){
355
356 int counter = 0;
357 int first_position;
358
359 rohc_debugf(2,"Coding IR packet (cid=%d)\n", context->cid);
360 //Both 1 and 3, 2 will be placed in dest[first_position]
361 counter = code_cid_values(context,dest,max_size,&first_position);
362
363 // 2
364 dest[first_position] = 0xfc;
365
366 // 4
367 dest[counter] = 0;
368 counter++;
369
370 // 5
371 dest[counter]= crc_calculate(CRC_TYPE_8,dest,counter);
372 counter++;
373 *payload_offset = 0;
374 return counter;
375 }
376 /*
377
378 Normal packet (5.10.2)
379
380 0 1 2 3 4 5 6 7
381 --- --- --- --- --- --- --- ---
382 1 : Add-CID octet : if for small CIDs and (CID != 0)
383 +---+---+---+---+---+---+---+---+
384 2 | first octet of IP packet |
385 +---+---+---+---+---+---+---+---+
386 : :
387 3 / 0-2 octets of CID info / 1-2 octets if for large CIDs
388 : :
389 +---+---+---+---+---+---+---+---+
390 | |
391 / rest of IP packet / variable length
392 | |
393 +---+---+---+---+---+---+---+---+
394
395 */
396 int uncompressed_code_normal_packet(struct sc_context *context,
397 const struct iphdr *ip,
398 unsigned char *dest,
399 int *payload_offset,
400 int max_size)
401 {
402
403 int counter = 0;
404 int first_position;
405
406
407 rohc_debugf(2,"Coding normal packet (cid=%d)\n", context->cid);
408 //Both 1 and 3, 2 will be placed in dest[first_position]
409 counter = code_cid_values(context,dest,max_size,&first_position);
410
411 // 2
412
413 dest[first_position] = ((unsigned char *)ip)[0];
414
415 *payload_offset = 1;
416 return counter;
417 }
418
419 /*
420 A struct thate every function must have the first fieldtell what protocol this profile has.
421 The second row is the profile id-number, Then two strings that is for printing version and
422 description. And finaly pointers to functions that have to exist in every profile.
423 */
424 struct sc_profile c_uncompressed_profile = {
425 0, // IP-Protocol
426 0, // Profile ID
427 "1.0b", // Version
428 "Uncompressed / Compressor", // Description
429 c_uncompressed_create,
430 c_uncompressed_destroy,
431 c_uncompressed_check_context,
432 c_uncompressed_encode,
433 c_uncompressed_feedback
434 };