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

# User Rev Content
1 pcg 1.1 /*
2     ROHC Project 2003 at Lulea University of Technology, Sweden.
3     Authors: Andreas Vernersson <andver-8@student.luth.se>
4     Daniel Pettersson <danpet-7@student.luth.se>
5     Erik Soderstrom <soderstrom@yahoo.com>
6     Fredrik Lindstrom <frelin-9@student.luth.se>
7     Johan Stenmark <johste-8@student.luth.se>
8     Martin Juhlin <juhlin@users.sourceforge.net>
9     Mikael Larsson <larmik-9@student.luth.se>
10     Robert Maxe <robmax-1@student.luth.se>
11    
12     Copyright (C) 2003 Andreas Vernersson, Daniel Pettersson,
13     Erik Soderström, Fredrik Lindström, Johan Stenmark,
14     Martin Juhlin, Mikael Larsson, Robert Maxe.
15    
16     This program is free software; you can redistribute it and/or modify
17     it under the terms of the GNU General Public License as published by
18     the Free Software Foundation; either version 2 of the License, or
19     (at your option) any later version.
20    
21     This program is distributed in the hope that it will be useful,
22     but WITHOUT ANY WARRANTY; without even the implied warranty of
23     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24     GNU General Public License for more details.
25    
26     You should have received a copy of the GNU General Public License
27     along with this program; if not, write to the Free Software
28     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29     */
30     /*
31     * Implementation of the 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     };