Small new_stack progress...

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4079 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2003-07-26 01:11:05 +00:00
parent 7c5fb432b0
commit 5e17f61acf
10 changed files with 355 additions and 256 deletions
+27 -35
View File
@@ -12,7 +12,6 @@
#include <Drivers.h> #include <Drivers.h>
#include "net_stack.h" #include "net_stack.h"
#include "net_layer.h"
status_t std_ops(int32 op, ...); status_t std_ops(int32 op, ...);
@@ -21,44 +20,16 @@ struct net_layer_module_info nlmi;
static struct net_stack_module_info *g_stack = NULL; static struct net_stack_module_info *g_stack = NULL;
// ------------------- // -------------------
status_t init(void * params) status_t init(net_layer *me)
{ {
status_t status; printf("%s: initing layer\n", me->name);
net_layer *layer1, *layer2; return B_OK;
layer2 = NULL;
status = B_NO_MEMORY;
layer1 = malloc(sizeof(*layer1));
if (!layer1)
goto error;
layer1->name = "ethernet/arp";
layer1->module = &nlmi;
layer2 = malloc(sizeof(*layer2));
if (!layer2)
goto error;
layer2->name = "arp/ethernet";
layer2->module = &nlmi;
status = g_stack->register_layer(layer1);
return g_stack->register_layer(layer2);
error:;
if (layer1)
free(layer1);
if (layer2)
free(layer2);
return status;
} }
status_t uninit(net_layer *me) status_t uninit(net_layer *me)
{ {
printf("%s: uniniting layer\n", me->name); printf("%s: uniniting layer\n", me->name);
free(me);
return B_OK; return B_OK;
} }
@@ -94,9 +65,30 @@ status_t output_buffer(net_layer *me, net_buffer *buffer)
status_t std_ops(int32 op, ...) status_t std_ops(int32 op, ...)
{ {
switch(op) { switch(op) {
case B_MODULE_INIT: case B_MODULE_INIT: {
status_t status;
net_layer *layer1, *layer2;
printf("arp: B_MODULE_INIT\n"); printf("arp: B_MODULE_INIT\n");
return get_module(NET_STACK_MODULE_NAME, (module_info **) &g_stack); status = get_module(NET_STACK_MODULE_NAME, (module_info **) &g_stack);
if (status != B_OK)
return status;
status = g_stack->register_layer("ethernet/arp", &nlmi, NULL, &layer1);
if (status != B_OK)
goto error1;
status = g_stack->register_layer("arp/ethernet", &nlmi, NULL, &layer2);
if (status != B_OK)
goto error2;
return B_OK;
error2:
g_stack->unregister_layer(layer1);
error1:
put_module(NET_STACK_MODULE_NAME);
return status;
}
case B_MODULE_UNINIT: case B_MODULE_UNINIT:
printf("arp: B_MODULE_UNINIT\n"); printf("arp: B_MODULE_UNINIT\n");
@@ -111,7 +103,7 @@ status_t std_ops(int32 op, ...)
struct net_layer_module_info nlmi = { struct net_layer_module_info nlmi = {
{ {
NET_LAYER_MODULE_ROOT "protocols/arp/v0", NET_LAYER_MODULES_ROOT "protocols/arp/v0",
0, 0,
std_ops std_ops
}, },
@@ -14,7 +14,6 @@
#include <Drivers.h> #include <Drivers.h>
#include "net_stack.h" #include "net_stack.h"
#include "net_layer.h"
enum { enum {
ETHER_GETADDR = B_DEVICE_OP_CODES_END, ETHER_GETADDR = B_DEVICE_OP_CODES_END,
@@ -26,12 +25,11 @@ enum {
ETHER_GETFRAMESIZE ETHER_GETFRAMESIZE
}; };
typedef struct ethernet_device_layer { typedef struct ethernet_device {
net_layer layer;
int fd; int fd;
int max_frame_size; int max_frame_size;
volatile thread_id reader_thread; volatile thread_id reader_thread;
} ethernet_device_layer; } ethernet_device;
#define ETHER_ADDR_LEN 6 /* Ethernet address length */ #define ETHER_ADDR_LEN 6 /* Ethernet address length */
#define ETHER_TYPE_LEN 2 /* Ethernet type field length */ #define ETHER_TYPE_LEN 2 /* Ethernet type field length */
@@ -58,36 +56,35 @@ static struct net_stack_module_info *g_stack = NULL;
// ------------------- // -------------------
status_t init(void * params) status_t init(net_layer *me)
{ {
return lookup_devices("/dev/net", params); printf("%s: initing layer\n", me->name);
return B_OK;
} }
status_t uninit(net_layer *me) status_t uninit(net_layer *me)
{ {
ethernet_device_layer *edl = (ethernet_device_layer *) me; ethernet_device *ed = me->cookie;
printf("%s: uniniting layer\n", me->name); printf("%s: uniniting layer\n", me->name);
close(edl->fd); close(ed->fd);
free(me->cookie);
free(me->name);
free(me);
return B_OK; return B_OK;
} }
status_t enable(net_layer *me, bool enable) status_t enable(net_layer *me, bool enable)
{ {
ethernet_device_layer *edl = (ethernet_device_layer *) me; ethernet_device *ed = me->cookie;
if (enable) { if (enable) {
// enable this layer // enable this layer
thread_id tid; thread_id tid;
char name[B_OS_NAME_LENGTH * 2]; char name[B_OS_NAME_LENGTH * 2];
if (edl->reader_thread != -1) if (ed->reader_thread != -1)
// already up // already up
return B_OK; return B_OK;
@@ -100,7 +97,7 @@ status_t enable(net_layer *me, bool enable)
return tid; return tid;
}; };
edl->reader_thread = tid; ed->reader_thread = tid;
return resume_thread(tid); return resume_thread(tid);
} else { } else {
@@ -108,14 +105,14 @@ status_t enable(net_layer *me, bool enable)
status_t dummy; status_t dummy;
// disable this layer // disable this layer
if (edl->reader_thread == -1) if (ed->reader_thread == -1)
// already down // already down
return B_OK; return B_OK;
send_signal_etc(edl->reader_thread, SIGTERM, 0); send_signal_etc(ed->reader_thread, SIGTERM, 0);
wait_for_thread(edl->reader_thread, &dummy); wait_for_thread(ed->reader_thread, &dummy);
printf("%s: device reader stopped.\n", me->name); printf("%s: device reader stopped.\n", me->name);
edl->reader_thread = -1; ed->reader_thread = -1;
return B_OK; return B_OK;
}; };
@@ -186,7 +183,7 @@ status_t lookup_devices(char *root, void *cookie)
status_t register_device(const char *path, void *cookie) status_t register_device(const char *path, void *cookie)
{ {
ethernet_device_layer *edl; ethernet_device *ed;
int frame_size; int frame_size;
ether_addr_t mac_address; ether_addr_t mac_address;
int fd; int fd;
@@ -232,32 +229,29 @@ status_t register_device(const char *path, void *cookie)
mac_address.byte[2], mac_address.byte[3], mac_address.byte[2], mac_address.byte[3],
mac_address.byte[4], mac_address.byte[5], frame_size); mac_address.byte[4], mac_address.byte[5], frame_size);
edl = malloc(sizeof(*edl)); ed = malloc(sizeof(*ed));
if (!edl) { if (!ed) {
close(fd); close(fd);
return B_NO_MEMORY; return B_NO_MEMORY;
}; };
edl->fd = fd; ed->fd = fd;
edl->max_frame_size = frame_size; ed->max_frame_size = frame_size;
edl->reader_thread = -1; ed->reader_thread = -1;
name = malloc(strlen("ethernet/") + strlen(path)); name = malloc(strlen("ethernet/") + strlen(path));
strcpy(name, "ethernet/"); strcpy(name, "ethernet/");
strcat(name, path + strlen("/dev/net/")); strcat(name, path + strlen("/dev/net/"));
edl->layer.name = name; return g_stack->register_layer(name, &nlmi, ed, NULL);
edl->layer.module = &nlmi;
return g_stack->register_layer(&edl->layer);
} }
// ---------------------------------------------------- // ----------------------------------------------------
status_t device_reader(void *args) status_t device_reader(void *args)
{ {
net_layer *me = args; net_layer *me = args;
ethernet_device_layer *edl = (ethernet_device_layer *) me; ethernet_device *ed = (ethernet_device *) me->cookie;
net_buffer *buffer; net_buffer *buffer;
status_t status; status_t status;
void *frame; void *frame;
ssize_t sz; ssize_t sz;
@@ -266,14 +260,14 @@ status_t device_reader(void *args)
status = B_OK; status = B_OK;
while(1) { while(1) {
frame = malloc(edl->max_frame_size); frame = malloc(ed->max_frame_size);
if (!frame) { if (!frame) {
status = B_NO_MEMORY; status = B_NO_MEMORY;
break; break;
}; };
// read on frame at time // read on frame at time
sz = read(edl->fd, frame, edl->max_frame_size); sz = read(ed->fd, frame, ed->max_frame_size);
if (sz >= B_OK) { if (sz >= B_OK) {
buffer = g_stack->new_buffer(); buffer = g_stack->new_buffer();
if (!buffer) { if (!buffer) {
@@ -293,7 +287,7 @@ status_t device_reader(void *args)
}; };
}; };
edl->reader_thread = -1; ed->reader_thread = -1;
return status; return status;
} }
@@ -302,9 +296,17 @@ status_t device_reader(void *args)
status_t std_ops(int32 op, ...) status_t std_ops(int32 op, ...)
{ {
switch(op) { switch(op) {
case B_MODULE_INIT: case B_MODULE_INIT: {
status_t status;
printf("ethernet: B_MODULE_INIT\n"); printf("ethernet: B_MODULE_INIT\n");
return get_module(NET_STACK_MODULE_NAME, (module_info **) &g_stack); status = get_module(NET_STACK_MODULE_NAME, (module_info **) &g_stack);
if (status != B_OK)
return status;
lookup_devices("/dev/net", NULL);
return B_OK;
};
case B_MODULE_UNINIT: case B_MODULE_UNINIT:
printf("ethernet: B_MODULE_UNINIT\n"); printf("ethernet: B_MODULE_UNINIT\n");
@@ -319,7 +321,7 @@ status_t std_ops(int32 op, ...)
struct net_layer_module_info nlmi = { struct net_layer_module_info nlmi = {
{ {
NET_LAYER_MODULE_ROOT "interfaces/ethernet", NET_LAYER_MODULES_ROOT "interfaces/ethernet",
0, 0,
std_ops std_ops
}, },
@@ -12,7 +12,6 @@
#include <Drivers.h> #include <Drivers.h>
#include "net_stack.h" #include "net_stack.h"
#include "net_layer.h"
status_t std_ops(int32 op, ...); status_t std_ops(int32 op, ...);
@@ -22,24 +21,15 @@ static struct net_stack_module_info *g_stack = NULL;
// ------------------- // -------------------
status_t init(void * params) status_t init(net_layer *me)
{ {
net_layer *layer; printf("%s: initing layer\n", me->name);
return B_OK;
layer = malloc(sizeof(*layer));
if (!layer)
return B_NO_MEMORY;
layer->name = "*/loopback";
layer->module = &nlmi;
return g_stack->register_layer(layer);
} }
status_t uninit(net_layer *me) status_t uninit(net_layer *me)
{ {
printf("%s: uniniting layer\n", me->name); printf("loopback: uniniting layer\n");
free(me);
return B_OK; return B_OK;
} }
@@ -63,9 +53,16 @@ status_t output_buffer(net_layer *me, net_buffer *buffer)
status_t std_ops(int32 op, ...) status_t std_ops(int32 op, ...)
{ {
switch(op) { switch(op) {
case B_MODULE_INIT: case B_MODULE_INIT: {
status_t status;
printf("loopback: B_MODULE_INIT\n"); printf("loopback: B_MODULE_INIT\n");
return get_module(NET_STACK_MODULE_NAME, (module_info **) &g_stack); status = get_module(NET_STACK_MODULE_NAME, (module_info **) &g_stack);
if (status != B_OK)
return status;
return g_stack->register_layer("*/loopback", &nlmi, NULL, NULL);
}
case B_MODULE_UNINIT: case B_MODULE_UNINIT:
printf("loopback: B_MODULE_UNINIT\n"); printf("loopback: B_MODULE_UNINIT\n");
@@ -80,7 +77,7 @@ status_t std_ops(int32 op, ...)
struct net_layer_module_info nlmi = { struct net_layer_module_info nlmi = {
{ {
NET_LAYER_MODULE_ROOT "interfaces/loopback", NET_LAYER_MODULES_ROOT "interfaces/loopback",
0, 0,
std_ops std_ops
}, },
@@ -68,6 +68,11 @@ int test_buffer()
g_stack->dump_buffer(buffer); g_stack->dump_buffer(buffer);
printf("Removing 61 bytes at offset 4...\n");
g_stack->remove_from_buffer(buffer, 4, 61);
g_stack->dump_buffer(buffer);
len = g_stack->read_buffer(buffer, 2, data, sizeof(data)); len = g_stack->read_buffer(buffer, 2, data, sizeof(data));
data[len] = 0; data[len] = 0;
+45 -3
View File
@@ -29,8 +29,40 @@ typedef int benaphore;
#define lock_benaphore(a) #define lock_benaphore(a)
#define unlock_benaphore(a) #define unlock_benaphore(a)
// Networking layer(s) definition // Networking layer(s) definitions
#include "net_layer.h" typedef struct net_layer net_layer;
#define NET_LAYER_MODULES_ROOT "network/layers/"
typedef struct net_layer_module_info {
module_info info;
status_t (*init)(net_layer *me);
status_t (*uninit)(net_layer *me);
status_t (*enable)(net_layer *me, bool enable);
status_t (*input_buffer)(net_layer *me, struct net_buffer *buffer);
status_t (*output_buffer)(net_layer *me, struct net_buffer *buffer);
} net_layer_module_info;
struct net_layer {
struct net_layer *next;
char *name;
net_layer_module_info *module;
void *cookie;
struct net_layer **layers_above;
struct net_layer **layers_below;
};
// Networking attributs
enum {
NET_ATTRIBUT_BOOL,
NET_ATTRIBUT_BYTE,
NET_ATTRIBUT_INT16,
NET_ATTRIBUT_INT32,
NET_ATTRIBUT_INT64,
NET_ATTRIBUT_DATA,
NET_ATTRIBUT_STRING,
NET_ATTRIBUT_POINTER
};
// Network stack main module definition // Network stack main module definition
@@ -48,8 +80,13 @@ struct net_stack_module_info {
* Net layers handling * Net layers handling
*/ */
status_t (*register_layer)(net_layer *layer); status_t (*register_layer)(const char *name, net_layer_module_info *module, void *cookie, net_layer **me);
status_t (*unregister_layer)(net_layer *layer); status_t (*unregister_layer)(net_layer *layer);
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 (*find_layer_attribut)(net_layer *layer, const char *name,
int *type, void **attribut, size_t *size);
status_t (*push_buffer_up)(net_layer *me, net_buffer *buffer); status_t (*push_buffer_up)(net_layer *me, net_buffer *buffer);
status_t (*push_buffer_down)(net_layer *me, net_buffer *buffer); status_t (*push_buffer_down)(net_layer *me, net_buffer *buffer);
@@ -77,6 +114,11 @@ struct net_stack_module_info {
uint32 (*read_buffer)(net_buffer *buffer, uint32 offset, void *data, uint32 bytes); uint32 (*read_buffer)(net_buffer *buffer, uint32 offset, void *data, uint32 bytes);
uint32 (*write_buffer)(net_buffer *buffer, uint32 offset, const void *data, uint32 bytes); uint32 (*write_buffer)(net_buffer *buffer, uint32 offset, const void *data, uint32 bytes);
status_t (*add_buffer_attribut)(net_buffer *buffer, const char *name, int type, ...);
status_t (*remove_buffer_attribut)(net_buffer *buffer, const char *name);
status_t (*find_buffer_attribut)(net_buffer *buffer, const char *name,
int *type, void **attribut, size_t *size);
void (*dump_buffer)(net_buffer *buffer); void (*dump_buffer)(net_buffer *buffer);
// Buffer queues support // Buffer queues support
+72 -117
View File
@@ -176,7 +176,7 @@ status_t delete_buffer(net_buffer *buffer, bool interrupt_safe)
return B_BAD_VALUE; return B_BAD_VALUE;
if (! g_buffers_pool) if (! g_buffers_pool)
// Uh? From where come this net_data!?! // Uh? From where come this net_buffer!?!
return B_ERROR; return B_ERROR;
printf("delete_buffer(%p)\n", buffer); printf("delete_buffer(%p)\n", buffer);
@@ -355,135 +355,69 @@ error1:
// -------------------------------------------------- // --------------------------------------------------
status_t remove_from_buffer(net_buffer *buffer, uint32 offset, uint32 bytes) status_t remove_from_buffer(net_buffer *buffer, uint32 offset, uint32 bytes)
{ {
#if 0 net_buffer_chunk *first_chunk;
// TODO!!! net_buffer_chunk *last_chunk;
net_buffer_chunk *previous_chunk;
net_buffer_chunk * ndn; uint32 offset_in_first_chunk;
net_buffer_chunk * start_node; uint32 offset_in_last_chunk;
net_buffer_chunk * end_node;
uint32 start_node_offset;
uint32 end_node_offset;
net_buffer_chunk * start_split_node;
net_buffer_chunk * end_split_node;
uint8 * data;
if (! buffer)
return B_BAD_VALUE;
if (offset >= buffer->len)
return B_BAD_VALUE;
if (bytes < 1) if (bytes < 1)
return B_BAD_VALUE; return B_BAD_VALUE;
/* first_chunk = find_buffer_chunk(buffer, offset, &offset_in_first_chunk, &previous_chunk);
Possibles cases: if (! first_chunk)
[XXXXXXX|++++++].... Triming at start of node (start and/or end nodes)
[+++|XXXXXX|+++].... Triming in the middle of *one* node
[+++++|XXXXXXXX].... Triming at the end of start node
...[XXXXXXXXXXXXXX].... Triming one or more full node
*/
start_node = find_buffer_chunk(nd, offset, &start_node_offset, NULL);
if (! start_node)
return B_BAD_VALUE; return B_BAD_VALUE;
end_node = find_buffer_chunk(nd, offset + bytes, &end_node_offset, NULL); last_chunk = find_buffer_chunk(buffer, offset + bytes, &offset_in_last_chunk, NULL);
if (! end_node) if (! last_chunk)
return B_BAD_VALUE; return B_BAD_VALUE;
if (offset_in_last_chunk) {
// we must split last_chunk data in two parts,
// removing beginnin chunk from data lists and adding the ending one :-(
if ( (start_node == end_node) && net_buffer_chunk *split_chunk;
(start_node_offset > 0) && (end_node_offset != end_node->len) ) uint8 *split;
// need to split one node into two parts, left & right, to be able to
// trim data in the middle:
// [++++|XXXXXX|+++++++]
return B_OK;
};
// if the trimmed part is in one node, we know now that it's:
// |++++++|XXXXXXXXXXXX|, or:
// |XXXXXXXXX|+++++++++|
if (start_node_offset)
start_node->len = start_node_offset;
if (end_node_offset) {
data = (uint8 *) end_node->data;
data += end_node_offset;
end_node->data = data;
end_node->len -= end_node_offset;
};
// start node must be split
split = (uint8 *) start_node->data;
split += start_node_offset;
start_split_node = new_buffer_chunk(split, start_node->len - start_node_offset);
if (! start_split_node)
goto error1;
};
if (end_node_offset) {
// end node must be split
split = (uint8 *) end_node->data;
split += end_node_offset;
end_split_node = new_buffer_chunk(split, end_node->len - end_node_offset);
if (! end_split_node)
goto error2;
};
if (start_split_node) {
};
ndn = start_node->next_data;
while (ndn->next_data != end_node) {
if (ndn->next_data == end_node)
break;
ndn = ndn->next_data;
};
!= end_node
if (end_split_node) {
};
// split start_node data chunk in two parts
start_node->len = start_node_offset;
start_split_node->free_func = NULL; // remove the beginning of last_chunk data
split = (uint8 *) last_chunk->data;
split += offset_in_last_chunk;
split_chunk = new_buffer_chunk(split, last_chunk->len - offset_in_last_chunk);
// if (! split_chunk)
// goto error1;
// as split_chunk data comes from 'last_chunk', we don't
// ask to free this chunk data, as it would be by previous_chunk
split_chunk->free_func = NULL;
split_chunk->next_data = last_chunk->next_data;
// add the split_chunk to buffer's all_chunks list
split_chunk->next = buffer->all_chunks;
buffer->all_chunks = split_chunk;
last_chunk = split_chunk;
}; };
if (offset_in_first_chunk) {
// remove the end of first_chunk data: just forgot about last bytes of data :-)
first_chunk->len = offset_in_first_chunk;
} else
first_chunk = previous_chunk;
ndn->len = offset_in_node; // fix the data chunks list to remove chunk(s), if any
if (first_chunk)
split_node->free_func = NULL; // as split_node data comes from 'ndn', we don't first_chunk->next_data = last_chunk;
// free this node data but only 'ndn' one... else
buffer->data_chunks = last_chunk;
// create a new node to host inserted data
new_node = new_buffer_chunk(data, bytes);
if (! new_node)
goto error2;
new_node->free_func = freethis; // can be NULL = don't free this chunk
new_node->free_cookie = NULL;
// add these nodes to node_list (nodes order don't matter in this list, so we do it the easy way :-)
split_node->next = nd->node_list;
new_node->next = split_node;
nd->node_list = new_node;
// Insert this new_node this node to the end of data_list
split_node->next_data = ndn->next_data;
ndn->next_data = new_node;
new_node->next_data = split_node;
nd->len -= bytes;
buffer->len -= bytes;
return B_OK; return B_OK;
error2:
g_memory_pool->delete_pool_node(g_buffer_chunks_pool, end_split_node);
error1:
if (start_split_node)
g_memory_pool->delete_pool_node(g_buffer_chunks_pool, start_split_node);
#endif
return B_ERROR;
} }
@@ -559,6 +493,27 @@ uint32 write_buffer(net_buffer *buffer, uint32 offset, const void *data, uint32
return len; return len;
} }
// --------------------------------------------------
status_t add_buffer_attribut(net_buffer *buffer, const char *name, int type, ...)
{
return B_ERROR;
}
// --------------------------------------------------
status_t remove_buffer_attribut(net_buffer *buffer, const char *name)
{
return B_ERROR;
}
status_t find_buffer_attribut(net_buffer *buffer, const char *name, int *type, void **attribut, size_t *size)
{
return B_ERROR;
}
// #pragma mark [data(s) queues functions] // #pragma mark [data(s) queues functions]
// -------------------------------------------------- // --------------------------------------------------
@@ -871,7 +826,7 @@ void dump_memory
for ( j = i; j < i+16 ; j++ ) for ( j = i; j < i+16 ; j++ )
{ {
if ( j < len ) if ( j < len )
sprintf(ptr, "%02x ",byte[j]); sprintf(ptr, "%02x ", byte[j]);
else else
sprintf(ptr, " "); sprintf(ptr, " ");
ptr += 3; ptr += 3;
@@ -32,6 +32,10 @@ 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 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 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 void dump_buffer(net_buffer *buffer); extern void dump_buffer(net_buffer *buffer);
// Network buffer(s) queue(s) // Network buffer(s) queue(s)
@@ -4,23 +4,32 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#include <stdarg.h>
#include <KernelExport.h> #include <KernelExport.h>
#include <OS.h> #include <OS.h>
#include <module.h>
#include "memory_pool.h"
#include "layers_manager.h" #include "layers_manager.h"
#include "buffer.h" #include "buffer.h"
/* Defines we need */
#define NET_LAYER_MODULES_ROOT "network/layers/"
struct layers_list { struct layers_list {
net_layer *first; struct net_layer *first;
sem_id lock; sem_id lock;
}; };
static struct layers_list g_layers; 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 status_t delete_layer(net_layer *layer);
extern struct memory_pool_module_info *g_memory_pool;
// #pragma mark [Start/Stop functions] // #pragma mark [Start/Stop functions]
@@ -54,13 +63,12 @@ status_t start_layers_manager()
if (!strlen(module_name)) if (!strlen(module_name))
continue; continue;
printf("layers_manager: loading %s layer(s) module\n", module_name);
if (get_module(module_name, (module_info **) &nlmi) != B_OK) if (get_module(module_name, (module_info **) &nlmi) != B_OK)
continue; continue;
printf("layers_manager: initing %s layer(s) module...\n", module_name);
// allow this module to register one or more interfaces
nlmi->init(NULL);
// this module may have been acquire more time by calling register_layer() // this module may have been acquire more time by calling register_layer()
// or have B_KEEP_LOADED flag, so we don't care...
put_module(module_name); put_module(module_name);
}; };
close_module_list(module_list); close_module_list(module_list);
@@ -70,6 +78,7 @@ status_t start_layers_manager()
acquire_sem(g_layers.lock); acquire_sem(g_layers.lock);
layer = g_layers.first; layer = g_layers.first;
while (layer) { while (layer) {
layer->module->init(layer);
layer->module->enable(layer, true); layer->module->enable(layer, true);
layer = layer->next; layer = layer->next;
}; };
@@ -90,7 +99,7 @@ status_t stop_layers_manager()
// TODO: handle multiple layers registered by same net module // TODO: handle multiple layers registered by same net module
// unregister all layers... // disable all layers...
layer = g_layers.first; layer = g_layers.first;
while (layer) { while (layer) {
next = layer->next; next = layer->next;
@@ -99,8 +108,12 @@ status_t stop_layers_manager()
// down the layer if currently up // down the layer if currently up
layer->module->enable(layer, false); layer->module->enable(layer, false);
layer->module->uninit(layer); layer->module->uninit(layer);
delete_layer(layer);
printf("layers_manager: unloading %s layer(s) module\n", module_name); printf("layers_manager: unloading %s layer(s) module\n", module_name);
put_module(module_name); put_module(module_name);
layer = next; layer = next;
}; };
@@ -114,39 +127,49 @@ status_t stop_layers_manager()
// #pragma mark [Public functions] // #pragma mark [Public functions]
// -------------------------------------------------- // --------------------------------------------------
status_t register_layer(net_layer *layer) status_t register_layer(const char *name, net_layer_module_info *module, void *cookie, net_layer **_layer)
{ {
status_t status; status_t status;
module_info *dummy; module_info *dummy;
net_layer *layer;
if (!layer) if (name == NULL ||
strlen(name) <= 0 ||
module == NULL)
return B_ERROR; return B_ERROR;
if (layer->module == NULL) layer = new_layer(name, module, cookie);
return B_ERROR; if (!layer)
return B_NO_MEMORY;
// acquire this module, to keep it loaded while this layer is registered // acquire this module, to keep it loaded while this layer is registered
status = get_module(layer->module->info.name, &dummy); status = get_module(module->info.name, &dummy);
if (status != B_OK) if (status != B_OK)
return status; goto error1;
layer->layers_above = NULL;
layer->layers_below = NULL;
status = acquire_sem(g_layers.lock); status = acquire_sem(g_layers.lock);
if (status != B_OK) if (status != B_OK)
return status; goto error2;
layer->next = g_layers.first; layer->next = g_layers.first;
g_layers.first = layer; g_layers.first = layer;
release_sem(g_layers.lock); release_sem(g_layers.lock);
printf("layers_manager: '%s' layer registered\n", layer->name); printf("layers_manager: '%s' layer registered\n", layer->name);
if (_layer)
*_layer = layer;
return B_OK; return B_OK;
error2:
put_module(module->info.name);
error1:
return status;
} }
// -------------------------------------------------- // --------------------------------------------------
status_t unregister_layer(net_layer *layer) status_t unregister_layer(net_layer *layer)
{ {
@@ -166,15 +189,57 @@ status_t unregister_layer(net_layer *layer)
while (p && p->next != layer) while (p && p->next != layer)
p = p->next; p = p->next;
if (!p) if (!p) {
// Oh oh... :-(
printf("layers_manager: unregister_layer(): %p layer not found in list!\n", layer); printf("layers_manager: unregister_layer(): %p layer not found in list!\n", layer);
else release_sem(g_layers.lock);
p->next = layer->next; return B_ERROR;
};
p->next = layer->next;
}; };
release_sem(g_layers.lock); release_sem(g_layers.lock);
layer->module->uninit(layer);
printf("layers_manager: '%s' layer unregistered\n", layer->name); printf("layers_manager: '%s' layer unregistered\n", layer->name);
put_module(layer->module->info.name);
return delete_layer(layer);
}
// --------------------------------------------------
status_t add_layer_attribut(net_layer *layer, const char *name, int type, ...)
{
va_list args;
va_start(args, type);
switch(type) {
case NET_ATTRIBUT_POINTER:
// hack
layer->cookie = va_arg(args, void *);
break;
}
va_end(args);
return B_OK;
}
// --------------------------------------------------
status_t remove_layer_attribut(net_layer *layer, const char *name)
{
return B_ERROR;
}
status_t find_layer_attribut(net_layer *layer, const char *name, int *type, void **attribut, size_t *size)
{
*attribut = &layer->cookie;
return B_OK; return B_OK;
} }
@@ -211,6 +276,7 @@ status_t push_buffer_up(net_layer *layer, net_buffer *buffer)
} }
// --------------------------------------------------
status_t push_buffer_down(net_layer *layer, net_buffer *buffer) status_t push_buffer_down(net_layer *layer, net_buffer *buffer)
{ {
net_layer *below; net_layer *below;
@@ -244,27 +310,50 @@ status_t push_buffer_down(net_layer *layer, net_buffer *buffer)
// #pragma mark [Private functions] // #pragma mark [Private functions]
#if 0 // --------------------------------------------------
// ---------------------------------------------------- static net_layer * new_layer(const char *name, net_layer_module_info *module, void *cookie)
status_t interface_reader(void *args)
{ {
ifnet_t *iface = args; net_layer *layer;
net_buffer *buffer;
status_t status; if (! g_layers_pool)
g_layers_pool = g_memory_pool->new_pool(sizeof(*layer), LAYERS_PER_POOL);
if (! g_layers_pool)
return NULL;
if (!iface || iface->module == NULL) layer = (net_layer *) g_memory_pool->new_pool_node(g_layers_pool);
if (! layer)
return NULL;
layer->name = strdup(name);
layer->module = module;
layer->cookie = cookie;
layer->layers_above = NULL;
layer->layers_below = NULL;
return layer;
}
// --------------------------------------------------
static status_t delete_layer(net_layer *layer)
{
if (!layer)
return B_ERROR;
if (! g_layers_pool)
// Uh? From where come this net_data!?!
return B_ERROR; return B_ERROR;
while(iface->if_flags & IFF_UP) { if (layer->name)
buffer = NULL; free(layer->name);
status = iface->module->receive_buffer(iface, &buffer); if (layer->layers_above)
if (status < B_OK || buffer == NULL) free(layer->layers_above);
continue; if (layer->layers_below)
free(layer->layers_below);
dump_buffer(buffer);
delete_buffer(buffer, false); return g_memory_pool->delete_pool_node(g_layers_pool, layer);
};
return B_OK;
} }
#endif
@@ -5,7 +5,7 @@
#ifndef OBOS_NET_STACK_LAYERS_MANAGER_H #ifndef OBOS_NET_STACK_LAYERS_MANAGER_H
#define OBOS_NET_STACK_LAYERS_MANAGER_H #define OBOS_NET_STACK_LAYERS_MANAGER_H
#include "net_layer.h" #include "net_stack.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -14,9 +14,15 @@ extern "C" {
extern status_t start_layers_manager(); extern status_t start_layers_manager();
extern status_t stop_layers_manager(); extern status_t stop_layers_manager();
extern status_t register_layer(net_layer *layer); extern status_t register_layer(const char *name, net_layer_module_info *module, void *cookie,
net_layer **me);
extern status_t unregister_layer(net_layer *layer); extern status_t unregister_layer(net_layer *layer);
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 push_buffer_up(net_layer *me, struct net_buffer *buffer); 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 push_buffer_down(net_layer *me, struct net_buffer *buffer);
@@ -73,6 +73,9 @@ struct net_stack_module_info nsmi = {
// Layers handling // Layers handling
register_layer, register_layer,
unregister_layer, unregister_layer,
add_layer_attribut,
remove_layer_attribut,
find_layer_attribut,
push_buffer_up, push_buffer_up,
push_buffer_down, push_buffer_down,
@@ -91,6 +94,10 @@ struct net_stack_module_info nsmi = {
read_buffer, read_buffer,
write_buffer, write_buffer,
add_buffer_attribut,
remove_buffer_attribut,
find_buffer_attribut,
dump_buffer, dump_buffer,