Draft attributes support added.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5888 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iovec.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <OS.h>
|
||||
|
||||
#include "net_stack.h"
|
||||
#include "memory_pool.h"
|
||||
#include "atomizer.h"
|
||||
#include "attribute.h"
|
||||
|
||||
#define DPRINTF printf
|
||||
|
||||
#define ATTRIBUTES_PER_POOL (64)
|
||||
|
||||
static memory_pool *g_attributes_pool = NULL;
|
||||
extern memory_pool_module_info *g_memory_pool;
|
||||
|
||||
#define DEFAULT_ATOMIZER (const void *) (-1)
|
||||
atomizer_module_info *g_atomizer = NULL;
|
||||
|
||||
// Privates prototypes
|
||||
// -------------------
|
||||
|
||||
// LET'S GO FOR IMPLEMENTATION
|
||||
// ------------------------------------
|
||||
|
||||
const void * register_attribute_id(const char *name)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
if (g_atomizer == NULL) {
|
||||
status = get_module(B_ATOMIZER_MODULE_NAME, (module_info **) &g_atomizer);
|
||||
if (status != B_OK) {
|
||||
dprintf("register_attribute_id(%s): Can't load " B_ATOMIZER_MODULE_NAME " module!\n", name);
|
||||
g_atomizer = (atomizer_module_info *) -1;
|
||||
};
|
||||
};
|
||||
|
||||
if (g_atomizer == (atomizer_module_info *) -1)
|
||||
return NULL;
|
||||
|
||||
return g_atomizer->atomize(DEFAULT_ATOMIZER, name, true);
|
||||
}
|
||||
|
||||
|
||||
net_attribute * new_attribute(net_attribute **in_list, const void *id)
|
||||
{
|
||||
net_attribute *attr;
|
||||
|
||||
if (! g_attributes_pool)
|
||||
g_attributes_pool = g_memory_pool->new_pool(sizeof(*attr), ATTRIBUTES_PER_POOL);
|
||||
|
||||
if (! g_attributes_pool)
|
||||
return NULL;
|
||||
|
||||
attr = (net_attribute *) g_memory_pool->new_pool_node(g_attributes_pool);
|
||||
if (! attr)
|
||||
return NULL;
|
||||
|
||||
attr->id = id;
|
||||
attr->type = 0;
|
||||
|
||||
if (in_list) {
|
||||
// prepend this attribut to the list
|
||||
attr->next = *in_list;
|
||||
*in_list = attr;
|
||||
} else
|
||||
attr->next = NULL;
|
||||
|
||||
return attr;
|
||||
|
||||
}
|
||||
|
||||
status_t delete_attribute(net_attribute *attr, net_attribute **from_list)
|
||||
{
|
||||
if (! attr)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (! g_attributes_pool)
|
||||
// Uh? From where come this net_attribute!?!
|
||||
return B_ERROR;
|
||||
|
||||
// dprintf("delete_attribute(%p, %p)\n", attr, from_list);
|
||||
|
||||
// Remove attribut from list, if any
|
||||
if (from_list) {
|
||||
if (*from_list == attr)
|
||||
*from_list = attr->next;
|
||||
else {
|
||||
net_attribute *tmp = *from_list;
|
||||
while (tmp) {
|
||||
if (tmp->next == attr)
|
||||
break;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
if (tmp)
|
||||
tmp->next = attr->next;
|
||||
}
|
||||
}
|
||||
|
||||
// Last, delete the net_buffer itself
|
||||
return g_memory_pool->delete_pool_node(g_attributes_pool, attr);
|
||||
}
|
||||
|
||||
|
||||
net_attribute * find_attribute(net_attribute *list, const void *id, int *type,
|
||||
void **value, size_t *size)
|
||||
{
|
||||
net_attribute *attr;
|
||||
|
||||
if (! list)
|
||||
return NULL;
|
||||
|
||||
// dprintf("find_attribute(%p, %p)\n", list, id);
|
||||
attr = list;
|
||||
while (attr) {
|
||||
if (attr->id == id) {
|
||||
if (type) *type = attr->type;
|
||||
if (size) *size = attr->size;
|
||||
if (value) {
|
||||
switch (attr->type & NET_ATTRIBUTE_TYPE_MASK) {
|
||||
case NET_ATTRIBUTE_BOOL: *value = &attr->u.boolean; break;
|
||||
case NET_ATTRIBUTE_BYTE: *value = &attr->u.byte; break;
|
||||
case NET_ATTRIBUTE_INT16: *value = &attr->u.word; break;
|
||||
case NET_ATTRIBUTE_INT32: *value = &attr->u.dword; break;
|
||||
case NET_ATTRIBUTE_INT64: *value = &attr->u.ddword; break;
|
||||
|
||||
case NET_ATTRIBUTE_DATA:
|
||||
case NET_ATTRIBUTE_STRING:
|
||||
*value = &attr->u.data;
|
||||
break;
|
||||
|
||||
case NET_ATTRIBUTE_POINTER:
|
||||
*value = attr->u.vec[0].iov_base;
|
||||
break;
|
||||
|
||||
case NET_ATTRIBUTE_IOVEC:
|
||||
*value = &attr->u.vec;
|
||||
break;
|
||||
};
|
||||
};
|
||||
return attr;
|
||||
};
|
||||
attr = attr->next;
|
||||
};
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/* attribute.h
|
||||
* private definitions for network attributes
|
||||
*/
|
||||
|
||||
#ifndef OBOS_NET_STACK_ATTRIBUTE_H
|
||||
#define OBOS_NET_STACK_ATTRIBUTE_H
|
||||
|
||||
#include <iovec.h>
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct net_attribute
|
||||
{
|
||||
struct net_attribute *next;
|
||||
const void *id;
|
||||
uint32 type;
|
||||
uint32 size;
|
||||
union {
|
||||
bool boolean;
|
||||
uint8 byte;
|
||||
uint16 word;
|
||||
uint32 dword;
|
||||
uint64 ddword;
|
||||
char data[256];
|
||||
void *ptr;
|
||||
iovec vec[16]; // Beware: 16 max :-(
|
||||
} u;
|
||||
} net_attribute;
|
||||
|
||||
extern const void * register_attribute_id(const char *name);
|
||||
extern net_attribute * new_attribute(net_attribute **in_list, const void *id);
|
||||
extern status_t delete_attribute(net_attribute *attribut, net_attribute **from_list);
|
||||
extern net_attribute * find_attribute(net_attribute *list, const void *id, int *type, void **value, size_t *size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OBOS_NET_STACK_ATTRIBUTE_H
|
||||
@@ -1,13 +1,17 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iovec.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <OS.h>
|
||||
|
||||
#include "memory_pool.h"
|
||||
#include "net_stack.h"
|
||||
#include "dump.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#include "attribute.h"
|
||||
|
||||
typedef struct net_buffer_chunk
|
||||
{
|
||||
@@ -28,8 +32,7 @@ struct net_buffer {
|
||||
uint32 flags;
|
||||
#define BUFFER_TO_FREE (1)
|
||||
#define BUFFER_IS_URGENT (2)
|
||||
// TODO: handle buffer attributs storage and lookup
|
||||
// struct attribut *attributs; // buffer attributs
|
||||
net_attribute *attributes; // buffer attributes
|
||||
};
|
||||
|
||||
struct net_buffer_queue
|
||||
@@ -62,7 +65,7 @@ static volatile sem_id g_buffers_purgatory_sync = -1; // use to notify buffers
|
||||
|
||||
static memory_pool * g_buffer_queues_pool = NULL;
|
||||
|
||||
extern struct memory_pool_module_info *g_memory_pool;
|
||||
extern memory_pool_module_info *g_memory_pool;
|
||||
|
||||
// Privates prototypes
|
||||
// -------------------
|
||||
@@ -121,7 +124,7 @@ status_t stop_buffers_service()
|
||||
wait_for_thread(g_buffers_purgatory_thread, &status);
|
||||
|
||||
// As the purgatory thread stop, some net_buffer(s) still could be flagged
|
||||
// BUFFER_TO_FREE, but not deleted... yet.
|
||||
// PACKET_TO_FREE, but not deleted... yet.
|
||||
g_memory_pool->for_each_pool_node(g_buffers_pool, buffer_killer, NULL);
|
||||
|
||||
// free buffers-related pools
|
||||
@@ -158,6 +161,7 @@ net_buffer * new_buffer(void)
|
||||
buffer->next = NULL;
|
||||
buffer->data_chunks = NULL;
|
||||
buffer->all_chunks = NULL;
|
||||
buffer->attributes = NULL;
|
||||
buffer->len = 0;
|
||||
buffer->flags = 0;
|
||||
|
||||
@@ -169,9 +173,6 @@ net_buffer * new_buffer(void)
|
||||
// --------------------------------------------------
|
||||
status_t delete_buffer(net_buffer *buffer, bool interrupt_safe)
|
||||
{
|
||||
net_buffer_chunk *chunk;
|
||||
net_buffer_chunk *next_chunk;
|
||||
|
||||
if (! buffer)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
@@ -190,31 +191,51 @@ status_t delete_buffer(net_buffer *buffer, bool interrupt_safe)
|
||||
return release_sem_etc(g_buffers_purgatory_sync, 1, B_DO_NOT_RESCHEDULE);
|
||||
};
|
||||
|
||||
// Okay, we can free each buffer chunk(s) right now!
|
||||
chunk = buffer->all_chunks;
|
||||
while (chunk) {
|
||||
// okay, one net_buffer_chunk less referencing this data
|
||||
chunk->ref_count--;
|
||||
next_chunk = chunk->next;
|
||||
|
||||
if (chunk->ref_count == 0) {
|
||||
// it was the last net_buffer_chunk to reference this data,
|
||||
// so free it now!
|
||||
if (buffer->all_chunks) {
|
||||
// Okay, we can (try to) free each buffer chunk(s) right now!
|
||||
|
||||
// do we have to call the free_func() on this data?
|
||||
if (chunk->free_func) {
|
||||
// yes, please!!!
|
||||
// call the right free_func kind on this data
|
||||
if (chunk->free_cookie)
|
||||
chunk->free_func(chunk->free_cookie, (void *) chunk->data);
|
||||
else
|
||||
chunk->free_func((void *) chunk->data);
|
||||
net_buffer_chunk *chunk;
|
||||
net_buffer_chunk *next_chunk;
|
||||
|
||||
chunk = buffer->all_chunks;
|
||||
while (chunk) {
|
||||
// okay, one net_buffer_chunk less referencing this data
|
||||
atomic_add(&chunk->ref_count, -1);
|
||||
next_chunk = chunk->next;
|
||||
|
||||
if (chunk->ref_count == 0) {
|
||||
// it was the last net_buffer_chunk to reference this data,
|
||||
// so free it now!
|
||||
|
||||
// do we have to call the free_func() on this data?
|
||||
if (chunk->free_func) {
|
||||
// yes, please!!!
|
||||
// call the right free_func kind on this data
|
||||
if (chunk->free_cookie)
|
||||
chunk->free_func(chunk->free_cookie, (void *) chunk->data);
|
||||
else
|
||||
chunk->free_func((void *) chunk->data);
|
||||
};
|
||||
// delete this net_buffer_chunk
|
||||
g_memory_pool->delete_pool_node(g_buffer_chunks_pool, chunk);
|
||||
};
|
||||
};
|
||||
// delete this net_buffer_chunk
|
||||
g_memory_pool->delete_pool_node(g_buffer_chunks_pool, chunk);
|
||||
|
||||
chunk = next_chunk;
|
||||
chunk = next_chunk;
|
||||
};
|
||||
};
|
||||
|
||||
if (buffer->attributes) {
|
||||
// Free buffer attributes
|
||||
|
||||
net_attribute *attr;
|
||||
net_attribute *next_attr;
|
||||
|
||||
attr = buffer->attributes;
|
||||
while (attr) {
|
||||
next_attr = attr->next;
|
||||
delete_attribute(attr, NULL);
|
||||
attr = next_attr;
|
||||
};
|
||||
};
|
||||
|
||||
// Last, delete the net_buffer itself
|
||||
@@ -232,7 +253,34 @@ net_buffer * duplicate_buffer(net_buffer *buffer)
|
||||
// --------------------------------------------------
|
||||
net_buffer * clone_buffer(net_buffer *buffer)
|
||||
{
|
||||
return NULL; // B_UNSUPPORTED;
|
||||
net_buffer *clone;
|
||||
net_buffer_chunk *chunk;
|
||||
|
||||
if (! g_buffers_pool)
|
||||
g_buffers_pool = g_memory_pool->new_pool(sizeof(*buffer), BUFFERS_PER_POOL);
|
||||
|
||||
if (! g_buffers_pool)
|
||||
return NULL;
|
||||
|
||||
clone = (net_buffer *) g_memory_pool->new_pool_node(g_buffers_pool);
|
||||
if (! clone)
|
||||
return NULL;
|
||||
|
||||
clone->next = NULL;
|
||||
clone->data_chunks = buffer->data_chunks;
|
||||
clone->all_chunks = buffer->all_chunks;
|
||||
clone->len = buffer->len;
|
||||
clone->flags = buffer->flags;
|
||||
|
||||
// Okay, increase all chunks ref count, as we have another buffer referencing them
|
||||
chunk = buffer->all_chunks;
|
||||
while (chunk) {
|
||||
// okay, one net_buffer_chunk less referencing this data
|
||||
atomic_add(&chunk->ref_count, 1);
|
||||
chunk = chunk->next;
|
||||
};
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
@@ -243,7 +291,7 @@ net_buffer * split_buffer(net_buffer *buffer, uint32 offset)
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
status_t merge_buffers(net_buffer *begin_buffer, net_buffer *end_buffer)
|
||||
status_t concatenate_buffers(net_buffer *begin_buffer, net_buffer *end_buffer)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
@@ -501,22 +549,112 @@ uint32 write_buffer(net_buffer *buffer, uint32 offset, const void *data, uint32
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
status_t add_buffer_attribut(net_buffer *buffer, const char *name, int type, ...)
|
||||
status_t add_buffer_attribute(net_buffer *buffer, const void *id, int type, ...)
|
||||
{
|
||||
return B_ERROR;
|
||||
net_attribute *attr;
|
||||
|
||||
if (! buffer)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
attr = new_attribute(&buffer->attributes, id);
|
||||
if (! attr)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (type & FROM_BUFFER) {
|
||||
va_list args;
|
||||
net_buffer_chunk *chunk;
|
||||
int offset;
|
||||
uint32 offset_in_chunk;
|
||||
int size;
|
||||
uint8 *ptr;
|
||||
|
||||
type = (type & NET_ATTRIBUTE_FLAGS_MASK);
|
||||
|
||||
va_start(args, type);
|
||||
offset = va_arg(args, int);
|
||||
size = va_arg(args, int);
|
||||
va_end(args);
|
||||
|
||||
chunk = find_buffer_chunk(buffer, offset, &offset_in_chunk, NULL);
|
||||
if (chunk == NULL) {
|
||||
delete_attribute(attr, &buffer->attributes);
|
||||
return B_BAD_VALUE;
|
||||
};
|
||||
|
||||
attr->size = size;
|
||||
|
||||
if (size < chunk->len - offset_in_chunk) {
|
||||
ptr = (uint8 *) chunk->data;
|
||||
ptr += offset_in_chunk;
|
||||
|
||||
attr->type = type | NET_ATTRIBUTE_POINTER;
|
||||
attr->u.ptr = ptr;
|
||||
} else {
|
||||
// data overlap this chunk, use iovec attribute type
|
||||
int i;
|
||||
uint32 len;
|
||||
uint32 chunk_len;
|
||||
|
||||
i = 0;
|
||||
len = 0;
|
||||
while (chunk) {
|
||||
ptr = (uint8 *) chunk->data;
|
||||
ptr += offset_in_chunk;
|
||||
chunk_len = min((chunk->len - offset_in_chunk), (size - len));
|
||||
|
||||
attr->u.vec[i].iov_base = ptr;
|
||||
attr->u.vec[i].iov_len = chunk_len;
|
||||
|
||||
len += chunk_len;
|
||||
i++;
|
||||
if (len >= size || i > 16)
|
||||
break;
|
||||
|
||||
offset_in_chunk = 0; // only the first chunk
|
||||
|
||||
chunk = chunk->next_data; // next chunk
|
||||
};
|
||||
|
||||
attr->type = type | NET_ATTRIBUTE_IOVEC;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Not implemented
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
status_t remove_buffer_attribut(net_buffer *buffer, const char *name)
|
||||
status_t remove_buffer_attribute(net_buffer *buffer, const void *id)
|
||||
{
|
||||
return B_ERROR;
|
||||
net_attribute *attr;
|
||||
|
||||
if (! buffer)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
attr = find_attribute(buffer->attributes, id, NULL, NULL, NULL);
|
||||
if (! attr)
|
||||
return B_NAME_NOT_FOUND;
|
||||
|
||||
return delete_attribute(attr, &buffer->attributes);
|
||||
}
|
||||
|
||||
|
||||
status_t find_buffer_attribut(net_buffer *buffer, const char *name, int *type, void **attribut, size_t *size)
|
||||
status_t find_buffer_attribute(net_buffer *buffer, const void *id, int *type, void **value, size_t *size)
|
||||
{
|
||||
return B_ERROR;
|
||||
net_attribute *attr;
|
||||
|
||||
if (! buffer)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
attr = find_attribute(buffer->attributes, id, type, value, size);
|
||||
if (! attr)
|
||||
return B_NAME_NOT_FOUND;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -810,56 +948,6 @@ static status_t append_buffer(net_buffer *buffer, const void *data, uint32 bytes
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
void dump_memory
|
||||
(
|
||||
const char * prefix,
|
||||
const void * data,
|
||||
uint32 len
|
||||
)
|
||||
{
|
||||
uint32 i,j;
|
||||
char text[96]; // only 3*16 + 16 max by line needed
|
||||
uint8 * byte;
|
||||
char * ptr;
|
||||
|
||||
byte = (uint8 *) data;
|
||||
|
||||
for ( i = 0; i < len; i += 16 )
|
||||
{
|
||||
ptr = text;
|
||||
|
||||
for ( j = i; j < i+16 ; j++ )
|
||||
{
|
||||
if ( j < len )
|
||||
sprintf(ptr, "%02x ", byte[j]);
|
||||
else
|
||||
sprintf(ptr, " ");
|
||||
ptr += 3;
|
||||
};
|
||||
|
||||
for (j = i; j < len && j < i+16;j++)
|
||||
{
|
||||
if ( byte[j] >= 0x20 && byte[j] < 0x7e )
|
||||
*ptr = byte[j];
|
||||
else
|
||||
*ptr = '.';
|
||||
|
||||
ptr++;
|
||||
};
|
||||
*ptr = '\n';
|
||||
ptr++;
|
||||
*ptr = '\0';
|
||||
|
||||
if (prefix)
|
||||
DPRINTF(prefix);
|
||||
DPRINTF(text);
|
||||
|
||||
// next line
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
void dump_buffer(net_buffer *buffer)
|
||||
{
|
||||
@@ -893,7 +981,7 @@ void dump_buffer(net_buffer *buffer)
|
||||
|
||||
}
|
||||
|
||||
// #pragma mark [Buffers Purgatory functions]
|
||||
// #pragma mark [Packets Purgatory functions]
|
||||
|
||||
// --------------------------------------------------
|
||||
static int32 buffers_purgatory_thread(void *data)
|
||||
|
||||
@@ -33,9 +33,9 @@ extern status_t attach_buffer_free_element(net_buffer *buffer, void *arg1, voi
|
||||
extern uint32 read_buffer(net_buffer *buffer, uint32 offset, void *data, uint32 bytes);
|
||||
extern uint32 write_buffer(net_buffer *buffer, uint32 offset, const void *data, uint32 bytes);
|
||||
|
||||
extern status_t add_buffer_attribut(net_buffer *buffer, const char *name, int type, ...);
|
||||
extern status_t remove_buffer_attribut(net_buffer *buffer, const char *name);
|
||||
extern status_t find_buffer_attribut(net_buffer *buffer, const char *name, int *type, void **attribut, size_t *size);
|
||||
extern status_t add_buffer_attribute(net_buffer *buffer, const void *id, int type, ...);
|
||||
extern status_t remove_buffer_attribute(net_buffer *buffer, const void *id);
|
||||
extern status_t find_buffer_attribute(net_buffer *buffer, const void *id, int *type, void **value, size_t *size);
|
||||
|
||||
extern void dump_buffer(net_buffer *buffer);
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <drivers/module.h>
|
||||
#include <drivers/KernelExport.h>
|
||||
|
||||
// --------------------------------------------------
|
||||
void dump_memory
|
||||
(
|
||||
const char * prefix,
|
||||
const void * data,
|
||||
uint32 len
|
||||
)
|
||||
{
|
||||
uint32 i,j;
|
||||
char text[96]; // only 3*16 + 16 max by line needed
|
||||
uint8 * byte;
|
||||
char * ptr;
|
||||
|
||||
byte = (uint8 *) data;
|
||||
|
||||
for ( i = 0; i < len; i += 16 )
|
||||
{
|
||||
ptr = text;
|
||||
|
||||
for ( j = i; j < i+16 ; j++ )
|
||||
{
|
||||
if ( j < len )
|
||||
sprintf(ptr, "%02x ", byte[j]);
|
||||
else
|
||||
sprintf(ptr, " ");
|
||||
ptr += 3;
|
||||
};
|
||||
|
||||
for (j = i; j < len && j < i+16;j++)
|
||||
{
|
||||
if ( byte[j] >= 0x20 && byte[j] < 0x7e )
|
||||
*ptr = byte[j];
|
||||
else
|
||||
*ptr = '.';
|
||||
|
||||
ptr++;
|
||||
};
|
||||
*ptr = '\n';
|
||||
ptr++;
|
||||
*ptr = '\0';
|
||||
|
||||
if (prefix)
|
||||
dprintf(prefix);
|
||||
dprintf(text);
|
||||
|
||||
// next line
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef DUMP_H
|
||||
#define DUMP_H
|
||||
|
||||
extern void dump_memory(const char *prefix, const void *data, uint32 len);
|
||||
|
||||
#endif
|
||||
@@ -24,10 +24,13 @@ static struct layers_list g_layers;
|
||||
static memory_pool * g_layers_pool = NULL;
|
||||
#define LAYERS_PER_POOL (64)
|
||||
|
||||
static net_layer * new_layer(const char *name, net_layer_module_info *module, void *cookie);
|
||||
static net_layer * new_layer(const char *name, const char *type, int priority,
|
||||
net_layer_module_info *module, void *cookie);
|
||||
static status_t delete_layer(net_layer *layer);
|
||||
|
||||
extern struct memory_pool_module_info *g_memory_pool;
|
||||
extern memory_pool_module_info *g_memory_pool;
|
||||
|
||||
char joker_type[] = "*";
|
||||
|
||||
|
||||
// #pragma mark [Start/Stop functions]
|
||||
@@ -63,7 +66,7 @@ status_t start_layers_manager()
|
||||
if (!strlen(module_name))
|
||||
continue;
|
||||
|
||||
printf("layers_manager: loading %s layer(s) module\n", module_name);
|
||||
dprintf("layers_manager: loading %s layer(s) module\n", module_name);
|
||||
if (get_module(module_name, (module_info **) &nlmi) != B_OK)
|
||||
continue;
|
||||
|
||||
@@ -104,14 +107,14 @@ status_t stop_layers_manager()
|
||||
while (layer) {
|
||||
next = layer->next;
|
||||
module_name = layer->module->info.name;
|
||||
printf("layers_manager: uniniting '%s' layer\n", layer->name);
|
||||
dprintf("layers_manager: uniniting '%s' layer\n", layer->name);
|
||||
// down the layer if currently up
|
||||
layer->module->enable(layer, false);
|
||||
layer->module->uninit(layer);
|
||||
|
||||
delete_layer(layer);
|
||||
|
||||
printf("layers_manager: unloading %s layer(s) module\n", module_name);
|
||||
dprintf("layers_manager: unloading %s layer(s) module\n", module_name);
|
||||
put_module(module_name);
|
||||
|
||||
layer = next;
|
||||
@@ -127,7 +130,8 @@ status_t stop_layers_manager()
|
||||
// #pragma mark [Public functions]
|
||||
|
||||
// --------------------------------------------------
|
||||
status_t register_layer(const char *name, net_layer_module_info *module, void *cookie, net_layer **_layer)
|
||||
status_t register_layer(const char *name, const char *type, int priority,
|
||||
net_layer_module_info *module, void *cookie, net_layer **_layer)
|
||||
{
|
||||
status_t status;
|
||||
module_info *dummy;
|
||||
@@ -138,7 +142,7 @@ status_t register_layer(const char *name, net_layer_module_info *module, void *c
|
||||
module == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
layer = new_layer(name, module, cookie);
|
||||
layer = new_layer(name, type, priority, module, cookie);
|
||||
if (!layer)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@@ -156,7 +160,7 @@ status_t register_layer(const char *name, net_layer_module_info *module, void *c
|
||||
|
||||
release_sem(g_layers.lock);
|
||||
|
||||
printf("layers_manager: '%s' layer registered\n", layer->name);
|
||||
dprintf("layers_manager: '%s' layer, registering %s/%s type\n", layer->name, layer->type, layer->sub_type);
|
||||
|
||||
if (_layer)
|
||||
*_layer = layer;
|
||||
@@ -191,7 +195,7 @@ status_t unregister_layer(net_layer *layer)
|
||||
|
||||
if (!p) {
|
||||
// Oh oh... :-(
|
||||
printf("layers_manager: unregister_layer(): %p layer not found in list!\n", layer);
|
||||
dprintf("layers_manager: unregister_layer(): %p layer not found in list!\n", layer);
|
||||
release_sem(g_layers.lock);
|
||||
return B_ERROR;
|
||||
};
|
||||
@@ -202,7 +206,7 @@ status_t unregister_layer(net_layer *layer)
|
||||
|
||||
layer->module->uninit(layer);
|
||||
|
||||
printf("layers_manager: '%s' layer unregistered\n", layer->name);
|
||||
dprintf("layers_manager: '%s' layer unregistered\n", layer->name);
|
||||
|
||||
put_module(layer->module->info.name);
|
||||
|
||||
@@ -235,14 +239,14 @@ net_layer * find_layer(const char *name)
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
status_t add_layer_attribut(net_layer *layer, const char *name, int type, ...)
|
||||
status_t add_layer_attribute(net_layer *layer, const void *id, int type, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, type);
|
||||
|
||||
switch(type) {
|
||||
case NET_ATTRIBUT_POINTER:
|
||||
case NET_ATTRIBUTE_DATA:
|
||||
// hack
|
||||
layer->cookie = va_arg(args, void *);
|
||||
break;
|
||||
@@ -255,53 +259,77 @@ status_t add_layer_attribut(net_layer *layer, const char *name, int type, ...)
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
status_t remove_layer_attribut(net_layer *layer, const char *name)
|
||||
status_t remove_layer_attribute(net_layer *layer, const void *id)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t find_layer_attribut(net_layer *layer, const char *name, int *type, void **attribut, size_t *size)
|
||||
status_t find_layer_attribute(net_layer *layer, const void *id, int *type,
|
||||
void **attribute, size_t *size)
|
||||
{
|
||||
*attribut = &layer->cookie;
|
||||
*attribute = &layer->cookie;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
status_t push_buffer_up(net_layer *layer, net_buffer *buffer)
|
||||
status_t send_up(net_layer *layer, net_buffer *buffer)
|
||||
{
|
||||
net_layer *above;
|
||||
status_t status;
|
||||
int i;
|
||||
// int i;
|
||||
|
||||
if (!layer)
|
||||
return B_ERROR;
|
||||
|
||||
// #### TODO: lock the layer(s) above & below hierarchy
|
||||
if (!layer->layers_above)
|
||||
// no layers above this one
|
||||
return B_ERROR;
|
||||
|
||||
status = B_ERROR;
|
||||
i = 0;
|
||||
while (layer->layers_above[i]) {
|
||||
above = layer->layers_above[i++];
|
||||
if (!above->module->input_buffer)
|
||||
// this layer don't input buffer
|
||||
continue;
|
||||
|
||||
status = above->module->input_buffer(above, buffer);
|
||||
if (status == B_OK)
|
||||
return status;
|
||||
};
|
||||
status = acquire_sem(g_layers.lock);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
status = B_ERROR;
|
||||
// TODO: lookup thru a previoulsy (at each layer [un]registration time) built list of
|
||||
// "above" layers of caller layer.
|
||||
|
||||
// dprintf("layers_manager: send_up(): layer %s (%s/%s), searching a matching upper layer...\n",
|
||||
// layer->name, layer->type, layer->sub_type);
|
||||
|
||||
// HACK: today, we lookup thru ALL :-( registered layers.
|
||||
// In the future, such layers (de)assembly should be done at layer (un)resgistration time, as
|
||||
// it never change until layers list change herself...
|
||||
above = g_layers.first;
|
||||
while (above) {
|
||||
// dprintf("layers_manager: send_up: Matching against layer %s (%s/%s) ?\n",
|
||||
// above->name, above->type, above->sub_type);
|
||||
|
||||
if ( above->module->process_input &&
|
||||
(strcmp(above->type, joker_type) == 0 ||
|
||||
(strcmp(above->type, layer->sub_type) == 0)) ) {
|
||||
/*
|
||||
dprintf("layers_manager: send_up: handing buffer from %s/%s (%s) to %s/%s (%s)...\n",
|
||||
layer->type, layer->sub_type, layer->name,
|
||||
above->type, above->sub_type, above->name);
|
||||
*/
|
||||
release_sem(g_layers.lock);
|
||||
status = above->module->process_input(above, buffer);
|
||||
if (status == B_OK) {
|
||||
atomic_add(&above->use_count, 1);
|
||||
return status;
|
||||
};
|
||||
|
||||
status = acquire_sem(g_layers.lock);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
};
|
||||
above = above->next;
|
||||
}
|
||||
release_sem(g_layers.lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
status_t push_buffer_down(net_layer *layer, net_buffer *buffer)
|
||||
status_t send_down(net_layer *layer, net_buffer *buffer)
|
||||
{
|
||||
net_layer *below;
|
||||
status_t status;
|
||||
@@ -319,11 +347,11 @@ status_t push_buffer_down(net_layer *layer, net_buffer *buffer)
|
||||
i = 0;
|
||||
while (layer->layers_below[i]) {
|
||||
below = layer->layers_below[i++];
|
||||
if (!below->module->output_buffer)
|
||||
// this layer don't output buffer
|
||||
if (!below->module->process_output)
|
||||
// this layer don't process output buffer
|
||||
continue;
|
||||
|
||||
status = below->module->output_buffer(below, buffer);
|
||||
status = below->module->process_output(below, buffer);
|
||||
if (status == B_OK)
|
||||
return status;
|
||||
};
|
||||
@@ -335,7 +363,8 @@ status_t push_buffer_down(net_layer *layer, net_buffer *buffer)
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
static net_layer * new_layer(const char *name, net_layer_module_info *module, void *cookie)
|
||||
static net_layer * new_layer(const char *name, const char *type, int priority,
|
||||
net_layer_module_info *module, void *cookie)
|
||||
{
|
||||
net_layer *layer;
|
||||
|
||||
@@ -349,9 +378,24 @@ static net_layer * new_layer(const char *name, net_layer_module_info *module, vo
|
||||
if (! layer)
|
||||
return NULL;
|
||||
|
||||
layer->name = strdup(name);
|
||||
layer->module = module;
|
||||
layer->cookie = cookie;
|
||||
layer->name = strdup(name);
|
||||
|
||||
if (type) {
|
||||
char *tmp, *t, *n;
|
||||
|
||||
tmp = strdup(type);
|
||||
t = strtok_r(tmp, "/", &n);
|
||||
layer->type = (t ? strdup(t) : joker_type);
|
||||
t = strtok_r(NULL, " ", &n);
|
||||
layer->sub_type = (t ? strdup(t) : joker_type);
|
||||
free(tmp);
|
||||
} else
|
||||
layer->type = layer->sub_type = NULL;
|
||||
|
||||
|
||||
layer->priority = priority;
|
||||
layer->module = module;
|
||||
layer->cookie = cookie;
|
||||
|
||||
layer->layers_above = NULL;
|
||||
layer->layers_below = NULL;
|
||||
@@ -372,6 +416,11 @@ static status_t delete_layer(net_layer *layer)
|
||||
|
||||
if (layer->name)
|
||||
free(layer->name);
|
||||
if (layer->type && layer->type != joker_type)
|
||||
free(layer->type);
|
||||
if (layer->sub_type && layer->type != joker_type)
|
||||
free(layer->sub_type);
|
||||
|
||||
if (layer->layers_above)
|
||||
free(layer->layers_above);
|
||||
if (layer->layers_below)
|
||||
|
||||
@@ -14,18 +14,18 @@ extern "C" {
|
||||
extern status_t start_layers_manager();
|
||||
extern status_t stop_layers_manager();
|
||||
|
||||
extern status_t register_layer(const char *name, net_layer_module_info *module, void *cookie,
|
||||
net_layer **me);
|
||||
extern status_t register_layer(const char *name, const char *type, int priority,
|
||||
net_layer_module_info *module, void *cookie, net_layer **layer);
|
||||
extern status_t unregister_layer(net_layer *layer);
|
||||
extern net_layer * find_layer(const char *name);
|
||||
|
||||
extern status_t add_layer_attribut(net_layer *layer, const char *name, int type, ...);
|
||||
extern status_t remove_layer_attribut(net_layer *layer, const char *name);
|
||||
extern status_t find_layer_attribut(net_layer *layer, const char *name,
|
||||
int *type, void **attribut, size_t *size);
|
||||
extern status_t add_layer_attribute(net_layer *layer, const void *id, int type, ...);
|
||||
extern status_t remove_layer_attribute(net_layer *layer, const void *id);
|
||||
extern status_t find_layer_attribute(net_layer *layer, const void *id,
|
||||
int *type, void **attribute, size_t *size);
|
||||
|
||||
extern status_t push_buffer_up(net_layer *me, struct net_buffer *buffer);
|
||||
extern status_t push_buffer_down(net_layer *me, struct net_buffer *buffer);
|
||||
extern status_t send_up(net_layer *me, struct net_buffer *buffer);
|
||||
extern status_t send_down(net_layer *me, struct net_buffer *buffer);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
#include "net_stack.h"
|
||||
#include "memory_pool.h"
|
||||
|
||||
#include "attribute.h"
|
||||
#include "layers_manager.h"
|
||||
#include "buffer.h"
|
||||
#include "timer.h"
|
||||
#include "dump.h"
|
||||
|
||||
memory_pool_module_info *g_memory_pool = NULL;
|
||||
|
||||
struct memory_pool_module_info *g_memory_pool = NULL;
|
||||
static bool g_started = false;
|
||||
|
||||
status_t std_ops(int32 op, ...);
|
||||
@@ -29,14 +32,14 @@ static status_t start(void)
|
||||
if (g_started)
|
||||
return B_OK;
|
||||
|
||||
puts("stack: starting...");
|
||||
dprintf("stack: starting...\n");
|
||||
|
||||
start_buffers_service();
|
||||
start_timers_service();
|
||||
|
||||
start_layers_manager();
|
||||
|
||||
puts("stack: started.");
|
||||
dprintf("stack: started.\n");
|
||||
g_started = true;
|
||||
|
||||
return B_OK;
|
||||
@@ -44,7 +47,7 @@ static status_t start(void)
|
||||
|
||||
static status_t stop(void)
|
||||
{
|
||||
puts("stack: stopping...");
|
||||
dprintf("stack: stopping...\n");
|
||||
|
||||
stop_layers_manager();
|
||||
|
||||
@@ -52,12 +55,13 @@ static status_t stop(void)
|
||||
stop_buffers_service();
|
||||
|
||||
|
||||
puts("stack: stopped.");
|
||||
dprintf("stack: stopped.\n");
|
||||
g_started = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
struct net_stack_module_info nsmi = {
|
||||
@@ -67,19 +71,23 @@ struct net_stack_module_info nsmi = {
|
||||
std_ops
|
||||
},
|
||||
|
||||
// Global stack control
|
||||
start,
|
||||
stop,
|
||||
|
||||
// Attributs IDs
|
||||
register_attribute_id,
|
||||
|
||||
// Layers handling
|
||||
register_layer,
|
||||
unregister_layer,
|
||||
find_layer,
|
||||
add_layer_attribut,
|
||||
remove_layer_attribut,
|
||||
find_layer_attribut,
|
||||
add_layer_attribute,
|
||||
remove_layer_attribute,
|
||||
find_layer_attribute,
|
||||
|
||||
push_buffer_up,
|
||||
push_buffer_down,
|
||||
send_up,
|
||||
send_down,
|
||||
|
||||
// net_buffer support
|
||||
new_buffer,
|
||||
@@ -96,9 +104,9 @@ struct net_stack_module_info nsmi = {
|
||||
read_buffer,
|
||||
write_buffer,
|
||||
|
||||
add_buffer_attribut,
|
||||
remove_buffer_attribut,
|
||||
find_buffer_attribut,
|
||||
add_buffer_attribute,
|
||||
remove_buffer_attribute,
|
||||
find_buffer_attribute,
|
||||
|
||||
dump_buffer,
|
||||
|
||||
@@ -114,7 +122,10 @@ struct net_stack_module_info nsmi = {
|
||||
delete_net_timer,
|
||||
start_net_timer,
|
||||
cancel_net_timer,
|
||||
net_timer_appointment
|
||||
net_timer_appointment,
|
||||
|
||||
// Misc.
|
||||
dump_memory
|
||||
};
|
||||
|
||||
status_t std_ops(int32 op, ...)
|
||||
@@ -123,11 +134,13 @@ status_t std_ops(int32 op, ...)
|
||||
|
||||
switch(op) {
|
||||
case B_MODULE_INIT:
|
||||
printf("stack: B_MODULE_INIT\n");
|
||||
dprintf("stack: B_MODULE_INIT\n");
|
||||
load_driver_symbols("stack");
|
||||
status = get_module(MEMORY_POOL_MODULE_NAME, (module_info **) &g_memory_pool);
|
||||
if (status != B_OK)
|
||||
if (status != B_OK) {
|
||||
dprintf("stack: Can't load " MEMORY_POOL_MODULE_NAME " module!\n");
|
||||
return status;
|
||||
};
|
||||
|
||||
// Re-publish memory_pool module api thru our
|
||||
nsmi.new_pool = g_memory_pool->new_pool;
|
||||
@@ -138,8 +151,7 @@ status_t std_ops(int32 op, ...)
|
||||
break;
|
||||
|
||||
case B_MODULE_UNINIT:
|
||||
// the stack is keeping loaded, so don't stop it
|
||||
printf("stack: B_MODULE_UNINIT\n");
|
||||
dprintf("stack: B_MODULE_UNINIT\n");
|
||||
put_module(MEMORY_POOL_MODULE_NAME);
|
||||
break;
|
||||
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user