00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #include <packet_server.h>
00038
00039 #include <align.h>
00040 #include <assert.h>
00041 #include <async.h>
00042 #include <errno.h>
00043 #include <fibril_synch.h>
00044 #include <unistd.h>
00045 #include <sys/mman.h>
00046 #include <ipc/packet.h>
00047 #include <ipc/net.h>
00048 #include <net/packet.h>
00049 #include <net/packet_header.h>
00050
00051 #define FREE_QUEUES_COUNT 7
00052
00054 #define DEFAULT_ADDR_LEN 32
00055
00057 #define DEFAULT_PREFIX 64
00058
00060 #define DEFAULT_SUFFIX 64
00061
00063 static struct {
00065 fibril_mutex_t lock;
00067 packet_t *free[FREE_QUEUES_COUNT];
00068
00074 size_t sizes[FREE_QUEUES_COUNT];
00075
00077 unsigned int count;
00078 } ps_globals = {
00079 .lock = FIBRIL_MUTEX_INITIALIZER(ps_globals.lock),
00080 .free = {
00081 NULL,
00082 NULL,
00083 NULL,
00084 NULL,
00085 NULL,
00086 NULL,
00087 NULL
00088 },
00089 .sizes = {
00090 PAGE_SIZE,
00091 PAGE_SIZE * 2,
00092 PAGE_SIZE * 4,
00093 PAGE_SIZE * 8,
00094 PAGE_SIZE * 16,
00095 PAGE_SIZE * 32,
00096 PAGE_SIZE * 64
00097 },
00098 .count = 0
00099 };
00100
00110 static void
00111 packet_init(packet_t *packet, size_t addr_len, size_t max_prefix,
00112 size_t max_content, size_t max_suffix)
00113 {
00114
00115 bzero(((void *) packet) + sizeof(packet_t),
00116 packet->length - sizeof(packet_t));
00117
00118
00119 packet->order = 0;
00120 packet->metric = 0;
00121 packet->previous = 0;
00122 packet->next = 0;
00123 packet->addr_len = 0;
00124 packet->src_addr = sizeof(packet_t);
00125 packet->dest_addr = packet->src_addr + addr_len;
00126 packet->max_prefix = max_prefix;
00127 packet->max_content = max_content;
00128 packet->data_start = packet->dest_addr + addr_len + packet->max_prefix;
00129 packet->data_end = packet->data_start;
00130 }
00131
00144 static packet_t *
00145 packet_create(size_t length, size_t addr_len, size_t max_prefix,
00146 size_t max_content, size_t max_suffix)
00147 {
00148 packet_t *packet;
00149 int rc;
00150
00151 assert(fibril_mutex_is_locked(&ps_globals.lock));
00152
00153
00154 packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
00155 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
00156 if (packet == MAP_FAILED)
00157 return NULL;
00158
00159 ps_globals.count++;
00160 packet->packet_id = ps_globals.count;
00161 packet->length = length;
00162 packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
00163 packet->magic_value = PACKET_MAGIC_VALUE;
00164 rc = pm_add(packet);
00165 if (rc != EOK) {
00166 munmap(packet, packet->length);
00167 return NULL;
00168 }
00169
00170 return packet;
00171 }
00172
00187 static packet_t *
00188 packet_get_local(size_t addr_len, size_t max_prefix, size_t max_content,
00189 size_t max_suffix)
00190 {
00191 size_t length = ALIGN_UP(sizeof(packet_t) + 2 * addr_len +
00192 max_prefix + max_content + max_suffix, PAGE_SIZE);
00193
00194 fibril_mutex_lock(&ps_globals.lock);
00195
00196 packet_t *packet;
00197 unsigned int index;
00198
00199 for (index = 0; index < FREE_QUEUES_COUNT; index++) {
00200 if ((length > ps_globals.sizes[index]) &&
00201 (index < FREE_QUEUES_COUNT - 1))
00202 continue;
00203
00204 packet = ps_globals.free[index];
00205 while (packet_is_valid(packet) && (packet->length < length))
00206 packet = pm_find(packet->next);
00207
00208 if (packet_is_valid(packet)) {
00209 if (packet == ps_globals.free[index])
00210 ps_globals.free[index] = pq_detach(packet);
00211 else
00212 pq_detach(packet);
00213
00214 packet_init(packet, addr_len, max_prefix, max_content,
00215 max_suffix);
00216 fibril_mutex_unlock(&ps_globals.lock);
00217
00218 return packet;
00219 }
00220 }
00221
00222 packet = packet_create(length, addr_len, max_prefix, max_content,
00223 max_suffix);
00224
00225 fibril_mutex_unlock(&ps_globals.lock);
00226
00227 return packet;
00228 }
00229
00235 static void packet_release(packet_t *packet)
00236 {
00237 int index;
00238 int result;
00239
00240 assert(fibril_mutex_is_locked(&ps_globals.lock));
00241
00242 for (index = 0; (index < FREE_QUEUES_COUNT - 1) &&
00243 (packet->length > ps_globals.sizes[index]); index++) {
00244 ;
00245 }
00246
00247 result = pq_add(&ps_globals.free[index], packet, packet->length,
00248 packet->length);
00249 assert(result == EOK);
00250 }
00251
00258 static int packet_release_wrapper(packet_id_t packet_id)
00259 {
00260 packet_t *packet;
00261
00262 packet = pm_find(packet_id);
00263 if (!packet_is_valid(packet))
00264 return ENOENT;
00265
00266 fibril_mutex_lock(&ps_globals.lock);
00267 pq_destroy(packet, packet_release);
00268 fibril_mutex_unlock(&ps_globals.lock);
00269
00270 return EOK;
00271 }
00272
00282 static int packet_reply(packet_t *packet)
00283 {
00284 ipc_callid_t callid;
00285 size_t size;
00286
00287 if (!packet_is_valid(packet))
00288 return EINVAL;
00289
00290 if (!async_share_in_receive(&callid, &size)) {
00291 async_answer_0(callid, EINVAL);
00292 return EINVAL;
00293 }
00294
00295 if (size != packet->length) {
00296 async_answer_0(callid, ENOMEM);
00297 return ENOMEM;
00298 }
00299
00300 return async_share_in_finalize(callid, packet,
00301 PROTO_READ | PROTO_WRITE);
00302 }
00303
00319 int
00320 packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
00321 size_t *answer_count)
00322 {
00323 packet_t *packet;
00324
00325 *answer_count = 0;
00326 switch (IPC_GET_IMETHOD(*call)) {
00327 case IPC_M_PHONE_HUNGUP:
00328 return EOK;
00329
00330 case NET_PACKET_CREATE_1:
00331 packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX,
00332 IPC_GET_CONTENT(*call), DEFAULT_SUFFIX);
00333 if (!packet)
00334 return ENOMEM;
00335 *answer_count = 2;
00336 IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
00337 IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
00338 return EOK;
00339
00340 case NET_PACKET_CREATE_4:
00341 packet = packet_get_local(
00342 ((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(*call)) ?
00343 IPC_GET_ADDR_LEN(*call) : DEFAULT_ADDR_LEN),
00344 DEFAULT_PREFIX + IPC_GET_PREFIX(*call),
00345 IPC_GET_CONTENT(*call),
00346 DEFAULT_SUFFIX + IPC_GET_SUFFIX(*call));
00347 if (!packet)
00348 return ENOMEM;
00349 *answer_count = 2;
00350 IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
00351 IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
00352 return EOK;
00353
00354 case NET_PACKET_GET:
00355 packet = pm_find(IPC_GET_ID(*call));
00356 if (!packet_is_valid(packet))
00357 return ENOENT;
00358 return packet_reply(packet);
00359
00360 case NET_PACKET_GET_SIZE:
00361 packet = pm_find(IPC_GET_ID(*call));
00362 if (!packet_is_valid(packet))
00363 return ENOENT;
00364 IPC_SET_ARG1(*answer, (sysarg_t) packet->length);
00365 *answer_count = 1;
00366 return EOK;
00367
00368 case NET_PACKET_RELEASE:
00369 return packet_release_wrapper(IPC_GET_ID(*call));
00370 }
00371
00372 return ENOTSUP;
00373 }
00374