ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/c_uncompressed.c
Revision: 1.1
Committed: Sun Feb 8 06:02:44 2004 UTC (20 years, 4 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: ROHC-IMPORT-2004-02-08
Log Message:
*** empty log message ***

File Contents

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