source: mainline/uspace/lib/socket/packet/packet.c@ 849ed54

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 849ed54 was 849ed54, checked in by Martin Decky <martin@…>, 15 years ago

Networking work:
Split the networking stack into end-user library (libsocket) and two helper libraries (libnet and libnetif).
Don't use over-the-hand compiling and linking, but rather separation of conserns.
There might be still some issues and the non-modular networking architecture is currently broken, but this will be fixed soon.

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup packet
30 * @{
31 */
32
33/** @file
34 * Packet map and queue implementation.
35 * This file has to be compiled with both the packet server and the client.
36 */
37
38#include <errno.h>
39#include <malloc.h>
40#include <mem.h>
41#include <fibril_synch.h>
42#include <unistd.h>
43
44#include <sys/mman.h>
45
46#include <net_err.h>
47#include <adt/generic_field.h>
48#include <packet/packet.h>
49#include <packet/packet_header.h>
50
51/** Packet map page size.
52 */
53#define PACKET_MAP_SIZE 100
54
55/** Returns the packet map page index.
56 * @param[in] packet_id The packet identifier.
57 */
58#define PACKET_MAP_PAGE(packet_id) (((packet_id) - 1) / PACKET_MAP_SIZE)
59
60/** Returns the packet index in the corresponding packet map page.
61 * @param[in] packet_id The packet identifier.
62 */
63#define PACKET_MAP_INDEX(packet_id) (((packet_id) - 1) % PACKET_MAP_SIZE)
64
65/** Type definition of the packet map page.
66 */
67typedef packet_t packet_map_t[PACKET_MAP_SIZE];
68/** Type definition of the packet map page pointer.
69 */
70typedef packet_map_t * packet_map_ref;
71
72/** Packet map.
73 * Maps packet identifiers to the packet references.
74 * @see generic_field.h
75 */
76GENERIC_FIELD_DECLARE(gpm, packet_map_t);
77
78/** Releases the packet.
79 * @param[in] packet The packet to be released.
80 * @returns EOK on success.
81 * @returns EINVAL if the packet is not valid.
82 */
83int packet_destroy(packet_t packet);
84
85/** Packet map global data.
86 */
87static struct{
88 /** Safety lock.
89 */
90 fibril_rwlock_t lock;
91 /** Packet map.
92 */
93 gpm_t packet_map;
94} pm_globals;
95
96GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t);
97
98int packet_destroy(packet_t packet){
99 if(! packet_is_valid(packet)){
100 return EINVAL;
101 }
102 return munmap(packet, packet->length);
103}
104
105int pm_init(void){
106 ERROR_DECLARE;
107
108 fibril_rwlock_initialize(&pm_globals.lock);
109 fibril_rwlock_write_lock(&pm_globals.lock);
110 ERROR_PROPAGATE(gpm_initialize(&pm_globals.packet_map));
111 fibril_rwlock_write_unlock(&pm_globals.lock);
112 return EOK;
113}
114
115packet_t pm_find(packet_id_t packet_id){
116 packet_map_ref map;
117 packet_t packet;
118
119 if(! packet_id){
120 return NULL;
121 }
122 fibril_rwlock_read_lock(&pm_globals.lock);
123 if(packet_id > PACKET_MAP_SIZE * gpm_count(&pm_globals.packet_map)){
124 fibril_rwlock_read_unlock(&pm_globals.lock);
125 return NULL;
126 }
127 map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet_id));
128 if(! map){
129 fibril_rwlock_read_unlock(&pm_globals.lock);
130 return NULL;
131 }
132 packet = (*map)[PACKET_MAP_INDEX(packet_id)];
133 fibril_rwlock_read_unlock(&pm_globals.lock);
134 return packet;
135}
136
137int pm_add(packet_t packet){
138 ERROR_DECLARE;
139
140 packet_map_ref map;
141
142 if(! packet_is_valid(packet)){
143 return EINVAL;
144 }
145 fibril_rwlock_write_lock(&pm_globals.lock);
146 if(PACKET_MAP_PAGE(packet->packet_id) < gpm_count(&pm_globals.packet_map)){
147 map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet->packet_id));
148 }else{
149 do{
150 map = (packet_map_ref) malloc(sizeof(packet_map_t));
151 if(! map){
152 fibril_rwlock_write_unlock(&pm_globals.lock);
153 return ENOMEM;
154 }
155 bzero(map, sizeof(packet_map_t));
156 if((ERROR_CODE = gpm_add(&pm_globals.packet_map, map)) < 0){
157 fibril_rwlock_write_unlock(&pm_globals.lock);
158 free(map);
159 return ERROR_CODE;
160 }
161 }while(PACKET_MAP_PAGE(packet->packet_id) >= gpm_count(&pm_globals.packet_map));
162 }
163 (*map)[PACKET_MAP_INDEX(packet->packet_id)] = packet;
164 fibril_rwlock_write_unlock(&pm_globals.lock);
165 return EOK;
166}
167
168void pm_destroy(void){
169 int count;
170 int index;
171 packet_map_ref map;
172 packet_t packet;
173
174 fibril_rwlock_write_lock(&pm_globals.lock);
175 count = gpm_count(&pm_globals.packet_map);
176 while(count > 0){
177 map = gpm_get_index(&pm_globals.packet_map, count - 1);
178 for(index = PACKET_MAP_SIZE - 1; index >= 0; -- index){
179 packet = (*map)[index];
180 if(packet_is_valid(packet)){
181 munmap(packet, packet->length);
182 }
183 }
184 }
185 gpm_destroy(&pm_globals.packet_map);
186 // leave locked
187}
188
189int pq_add(packet_t * first, packet_t packet, size_t order, size_t metric){
190 packet_t item;
191
192 if((! first) || (! packet_is_valid(packet))){
193 return EINVAL;
194 }
195 pq_set_order(packet, order, metric);
196 if(packet_is_valid(*first)){
197 item = * first;
198 do{
199 if(item->order < order){
200 if(item->next){
201 item = pm_find(item->next);
202 }else{
203 item->next = packet->packet_id;
204 packet->previous = item->packet_id;
205 return EOK;
206 }
207 }else{
208 packet->previous = item->previous;
209 packet->next = item->packet_id;
210 item->previous = packet->packet_id;
211 item = pm_find(packet->previous);
212 if(item){
213 item->next = packet->packet_id;
214 }else{
215 *first = packet;
216 }
217 return EOK;
218 }
219 }while(packet_is_valid(item));
220 }
221 *first = packet;
222 return EOK;
223}
224
225packet_t pq_find(packet_t packet, size_t order){
226 packet_t item;
227
228 if(! packet_is_valid(packet)){
229 return NULL;
230 }
231 item = packet;
232 do{
233 if(item->order == order){
234 return item;
235 }
236 item = pm_find(item->next);
237 }while(item && (item != packet) && packet_is_valid(item));
238 return NULL;
239}
240
241int pq_insert_after(packet_t packet, packet_t new_packet){
242 packet_t item;
243
244 if(!(packet_is_valid(packet) && packet_is_valid(new_packet))){
245 return EINVAL;
246 }
247 new_packet->previous = packet->packet_id;
248 new_packet->next = packet->next;
249 item = pm_find(packet->next);
250 if(item){
251 item->previous = new_packet->packet_id;
252 }
253 packet->next = new_packet->packet_id;
254 return EOK;
255}
256
257packet_t pq_detach(packet_t packet){
258 packet_t next;
259 packet_t previous;
260
261 if(! packet_is_valid(packet)){
262 return NULL;
263 }
264 next = pm_find(packet->next);
265 if(next){
266 next->previous = packet->previous;
267 previous = pm_find(next->previous);
268 if(previous){
269 previous->next = next->packet_id;
270 }
271 }
272 packet->previous = 0;
273 packet->next = 0;
274 return next;
275}
276
277int pq_set_order(packet_t packet, size_t order, size_t metric){
278 if(! packet_is_valid(packet)){
279 return EINVAL;
280 }
281 packet->order = order;
282 packet->metric = metric;
283 return EOK;
284}
285
286int pq_get_order(packet_t packet, size_t * order, size_t * metric){
287 if(! packet_is_valid(packet)){
288 return EINVAL;
289 }
290 if(order){
291 *order = packet->order;
292 }
293 if(metric){
294 *metric = packet->metric;
295 }
296 return EOK;
297}
298
299void pq_destroy(packet_t first, void (*packet_release)(packet_t packet)){
300 packet_t actual;
301 packet_t next;
302
303 actual = first;
304 while(packet_is_valid(actual)){
305 next = pm_find(actual->next);
306 actual->next = 0;
307 actual->previous = 0;
308 if(packet_release){
309 packet_release(actual);
310 }
311 actual = next;
312 }
313}
314
315packet_t pq_next(packet_t packet){
316 if(! packet_is_valid(packet)){
317 return NULL;
318 }
319 return pm_find(packet->next);
320}
321
322packet_t pq_previous(packet_t packet){
323 if(! packet_is_valid(packet)){
324 return NULL;
325 }
326 return pm_find(packet->previous);
327}
328
329/** @}
330 */
Note: See TracBrowser for help on using the repository browser.