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, 2 months 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

# 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 pcg 1.3 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 pcg 1.1 */
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     };