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:
parent
7c5fb432b0
commit
5e17f61acf
@ -12,7 +12,6 @@
|
||||
#include <Drivers.h>
|
||||
|
||||
#include "net_stack.h"
|
||||
#include "net_layer.h"
|
||||
|
||||
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;
|
||||
|
||||
// -------------------
|
||||
status_t init(void * params)
|
||||
status_t init(net_layer *me)
|
||||
{
|
||||
status_t status;
|
||||
net_layer *layer1, *layer2;
|
||||
printf("%s: initing layer\n", me->name);
|
||||
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)
|
||||
{
|
||||
printf("%s: uniniting layer\n", me->name);
|
||||
|
||||
free(me);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -94,9 +65,30 @@ status_t output_buffer(net_layer *me, net_buffer *buffer)
|
||||
status_t std_ops(int32 op, ...)
|
||||
{
|
||||
switch(op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_INIT: {
|
||||
status_t status;
|
||||
net_layer *layer1, *layer2;
|
||||
|
||||
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:
|
||||
printf("arp: B_MODULE_UNINIT\n");
|
||||
@ -111,7 +103,7 @@ status_t std_ops(int32 op, ...)
|
||||
|
||||
struct net_layer_module_info nlmi = {
|
||||
{
|
||||
NET_LAYER_MODULE_ROOT "protocols/arp/v0",
|
||||
NET_LAYER_MODULES_ROOT "protocols/arp/v0",
|
||||
0,
|
||||
std_ops
|
||||
},
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <Drivers.h>
|
||||
|
||||
#include "net_stack.h"
|
||||
#include "net_layer.h"
|
||||
|
||||
enum {
|
||||
ETHER_GETADDR = B_DEVICE_OP_CODES_END,
|
||||
@ -26,12 +25,11 @@ enum {
|
||||
ETHER_GETFRAMESIZE
|
||||
};
|
||||
|
||||
typedef struct ethernet_device_layer {
|
||||
net_layer layer;
|
||||
typedef struct ethernet_device {
|
||||
int fd;
|
||||
int max_frame_size;
|
||||
volatile thread_id reader_thread;
|
||||
} ethernet_device_layer;
|
||||
} ethernet_device;
|
||||
|
||||
#define ETHER_ADDR_LEN 6 /* Ethernet address 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)
|
||||
{
|
||||
ethernet_device_layer *edl = (ethernet_device_layer *) me;
|
||||
ethernet_device *ed = me->cookie;
|
||||
|
||||
printf("%s: uniniting layer\n", me->name);
|
||||
|
||||
close(edl->fd);
|
||||
close(ed->fd);
|
||||
free(me->cookie);
|
||||
|
||||
free(me->name);
|
||||
free(me);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t enable(net_layer *me, bool enable)
|
||||
{
|
||||
ethernet_device_layer *edl = (ethernet_device_layer *) me;
|
||||
ethernet_device *ed = me->cookie;
|
||||
|
||||
if (enable) {
|
||||
// enable this layer
|
||||
thread_id tid;
|
||||
char name[B_OS_NAME_LENGTH * 2];
|
||||
|
||||
if (edl->reader_thread != -1)
|
||||
if (ed->reader_thread != -1)
|
||||
// already up
|
||||
return B_OK;
|
||||
|
||||
@ -100,7 +97,7 @@ status_t enable(net_layer *me, bool enable)
|
||||
return tid;
|
||||
};
|
||||
|
||||
edl->reader_thread = tid;
|
||||
ed->reader_thread = tid;
|
||||
return resume_thread(tid);
|
||||
|
||||
} else {
|
||||
@ -108,14 +105,14 @@ status_t enable(net_layer *me, bool enable)
|
||||
status_t dummy;
|
||||
|
||||
// disable this layer
|
||||
if (edl->reader_thread == -1)
|
||||
if (ed->reader_thread == -1)
|
||||
// already down
|
||||
return B_OK;
|
||||
|
||||
send_signal_etc(edl->reader_thread, SIGTERM, 0);
|
||||
wait_for_thread(edl->reader_thread, &dummy);
|
||||
send_signal_etc(ed->reader_thread, SIGTERM, 0);
|
||||
wait_for_thread(ed->reader_thread, &dummy);
|
||||
printf("%s: device reader stopped.\n", me->name);
|
||||
edl->reader_thread = -1;
|
||||
ed->reader_thread = -1;
|
||||
return B_OK;
|
||||
};
|
||||
|
||||
@ -186,7 +183,7 @@ status_t lookup_devices(char *root, void *cookie)
|
||||
|
||||
status_t register_device(const char *path, void *cookie)
|
||||
{
|
||||
ethernet_device_layer *edl;
|
||||
ethernet_device *ed;
|
||||
int frame_size;
|
||||
ether_addr_t mac_address;
|
||||
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[4], mac_address.byte[5], frame_size);
|
||||
|
||||
edl = malloc(sizeof(*edl));
|
||||
if (!edl) {
|
||||
ed = malloc(sizeof(*ed));
|
||||
if (!ed) {
|
||||
close(fd);
|
||||
return B_NO_MEMORY;
|
||||
};
|
||||
|
||||
edl->fd = fd;
|
||||
edl->max_frame_size = frame_size;
|
||||
edl->reader_thread = -1;
|
||||
ed->fd = fd;
|
||||
ed->max_frame_size = frame_size;
|
||||
ed->reader_thread = -1;
|
||||
|
||||
name = malloc(strlen("ethernet/") + strlen(path));
|
||||
strcpy(name, "ethernet/");
|
||||
strcat(name, path + strlen("/dev/net/"));
|
||||
|
||||
edl->layer.name = name;
|
||||
edl->layer.module = &nlmi;
|
||||
|
||||
return g_stack->register_layer(&edl->layer);
|
||||
return g_stack->register_layer(name, &nlmi, ed, NULL);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
status_t device_reader(void *args)
|
||||
{
|
||||
net_layer *me = args;
|
||||
ethernet_device_layer *edl = (ethernet_device_layer *) me;
|
||||
net_buffer *buffer;
|
||||
net_layer *me = args;
|
||||
ethernet_device *ed = (ethernet_device *) me->cookie;
|
||||
net_buffer *buffer;
|
||||
status_t status;
|
||||
void *frame;
|
||||
ssize_t sz;
|
||||
@ -266,14 +260,14 @@ status_t device_reader(void *args)
|
||||
|
||||
status = B_OK;
|
||||
while(1) {
|
||||
frame = malloc(edl->max_frame_size);
|
||||
frame = malloc(ed->max_frame_size);
|
||||
if (!frame) {
|
||||
status = B_NO_MEMORY;
|
||||
break;
|
||||
};
|
||||
|
||||
// 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) {
|
||||
buffer = g_stack->new_buffer();
|
||||
if (!buffer) {
|
||||
@ -293,7 +287,7 @@ status_t device_reader(void *args)
|
||||
};
|
||||
};
|
||||
|
||||
edl->reader_thread = -1;
|
||||
ed->reader_thread = -1;
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -302,9 +296,17 @@ status_t device_reader(void *args)
|
||||
status_t std_ops(int32 op, ...)
|
||||
{
|
||||
switch(op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_INIT: {
|
||||
status_t status;
|
||||
|
||||
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:
|
||||
printf("ethernet: B_MODULE_UNINIT\n");
|
||||
@ -319,7 +321,7 @@ status_t std_ops(int32 op, ...)
|
||||
|
||||
struct net_layer_module_info nlmi = {
|
||||
{
|
||||
NET_LAYER_MODULE_ROOT "interfaces/ethernet",
|
||||
NET_LAYER_MODULES_ROOT "interfaces/ethernet",
|
||||
0,
|
||||
std_ops
|
||||
},
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <Drivers.h>
|
||||
|
||||
#include "net_stack.h"
|
||||
#include "net_layer.h"
|
||||
|
||||
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;
|
||||
|
||||
layer = malloc(sizeof(*layer));
|
||||
if (!layer)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
layer->name = "*/loopback";
|
||||
layer->module = &nlmi;
|
||||
|
||||
return g_stack->register_layer(layer);
|
||||
printf("%s: initing layer\n", me->name);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t uninit(net_layer *me)
|
||||
{
|
||||
printf("%s: uniniting layer\n", me->name);
|
||||
free(me);
|
||||
printf("loopback: uniniting layer\n");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -63,9 +53,16 @@ status_t output_buffer(net_layer *me, net_buffer *buffer)
|
||||
status_t std_ops(int32 op, ...)
|
||||
{
|
||||
switch(op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_INIT: {
|
||||
status_t status;
|
||||
|
||||
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:
|
||||
printf("loopback: B_MODULE_UNINIT\n");
|
||||
@ -80,7 +77,7 @@ status_t std_ops(int32 op, ...)
|
||||
|
||||
struct net_layer_module_info nlmi = {
|
||||
{
|
||||
NET_LAYER_MODULE_ROOT "interfaces/loopback",
|
||||
NET_LAYER_MODULES_ROOT "interfaces/loopback",
|
||||
0,
|
||||
std_ops
|
||||
},
|
||||
|
@ -68,6 +68,11 @@ int test_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));
|
||||
data[len] = 0;
|
||||
|
||||
|
@ -29,8 +29,40 @@ typedef int benaphore;
|
||||
#define lock_benaphore(a)
|
||||
#define unlock_benaphore(a)
|
||||
|
||||
// Networking layer(s) definition
|
||||
#include "net_layer.h"
|
||||
// Networking layer(s) definitions
|
||||
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
|
||||
|
||||
@ -48,8 +80,13 @@ struct net_stack_module_info {
|
||||
* 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 (*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_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 (*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);
|
||||
|
||||
// Buffer queues support
|
||||
|
@ -176,7 +176,7 @@ status_t delete_buffer(net_buffer *buffer, bool interrupt_safe)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (! g_buffers_pool)
|
||||
// Uh? From where come this net_data!?!
|
||||
// Uh? From where come this net_buffer!?!
|
||||
return B_ERROR;
|
||||
|
||||
printf("delete_buffer(%p)\n", buffer);
|
||||
@ -355,135 +355,69 @@ error1:
|
||||
// --------------------------------------------------
|
||||
status_t remove_from_buffer(net_buffer *buffer, uint32 offset, uint32 bytes)
|
||||
{
|
||||
#if 0
|
||||
// TODO!!!
|
||||
|
||||
net_buffer_chunk * ndn;
|
||||
net_buffer_chunk * start_node;
|
||||
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;
|
||||
net_buffer_chunk *first_chunk;
|
||||
net_buffer_chunk *last_chunk;
|
||||
net_buffer_chunk *previous_chunk;
|
||||
uint32 offset_in_first_chunk;
|
||||
uint32 offset_in_last_chunk;
|
||||
|
||||
if (! buffer)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (offset >= buffer->len)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (bytes < 1)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
/*
|
||||
Possibles cases:
|
||||
[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)
|
||||
first_chunk = find_buffer_chunk(buffer, offset, &offset_in_first_chunk, &previous_chunk);
|
||||
if (! first_chunk)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
end_node = find_buffer_chunk(nd, offset + bytes, &end_node_offset, NULL);
|
||||
if (! end_node)
|
||||
|
||||
last_chunk = find_buffer_chunk(buffer, offset + bytes, &offset_in_last_chunk, NULL);
|
||||
if (! last_chunk)
|
||||
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) &&
|
||||
(start_node_offset > 0) && (end_node_offset != end_node->len) )
|
||||
// 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;
|
||||
net_buffer_chunk *split_chunk;
|
||||
uint8 *split;
|
||||
|
||||
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;
|
||||
|
||||
split_node->free_func = NULL; // as split_node data comes from 'ndn', we don't
|
||||
// free this node data but only 'ndn' one...
|
||||
|
||||
// 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;
|
||||
// fix the data chunks list to remove chunk(s), if any
|
||||
if (first_chunk)
|
||||
first_chunk->next_data = last_chunk;
|
||||
else
|
||||
buffer->data_chunks = last_chunk;
|
||||
|
||||
buffer->len -= bytes;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
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]
|
||||
|
||||
// --------------------------------------------------
|
||||
@ -871,7 +826,7 @@ void dump_memory
|
||||
for ( j = i; j < i+16 ; j++ )
|
||||
{
|
||||
if ( j < len )
|
||||
sprintf(ptr, "%02x ",byte[j]);
|
||||
sprintf(ptr, "%02x ", byte[j]);
|
||||
else
|
||||
sprintf(ptr, " ");
|
||||
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 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);
|
||||
|
||||
// Network buffer(s) queue(s)
|
||||
|
@ -4,23 +4,32 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <OS.h>
|
||||
#include <module.h>
|
||||
|
||||
#include "memory_pool.h"
|
||||
#include "layers_manager.h"
|
||||
#include "buffer.h"
|
||||
|
||||
/* Defines we need */
|
||||
#define NET_LAYER_MODULES_ROOT "network/layers/"
|
||||
|
||||
struct layers_list {
|
||||
net_layer *first;
|
||||
sem_id lock;
|
||||
struct net_layer *first;
|
||||
sem_id lock;
|
||||
};
|
||||
|
||||
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]
|
||||
|
||||
|
||||
@ -54,13 +63,12 @@ status_t start_layers_manager()
|
||||
if (!strlen(module_name))
|
||||
continue;
|
||||
|
||||
printf("layers_manager: loading %s layer(s) module\n", module_name);
|
||||
if (get_module(module_name, (module_info **) &nlmi) != B_OK)
|
||||
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()
|
||||
// or have B_KEEP_LOADED flag, so we don't care...
|
||||
put_module(module_name);
|
||||
};
|
||||
close_module_list(module_list);
|
||||
@ -70,6 +78,7 @@ status_t start_layers_manager()
|
||||
acquire_sem(g_layers.lock);
|
||||
layer = g_layers.first;
|
||||
while (layer) {
|
||||
layer->module->init(layer);
|
||||
layer->module->enable(layer, true);
|
||||
layer = layer->next;
|
||||
};
|
||||
@ -90,7 +99,7 @@ status_t stop_layers_manager()
|
||||
|
||||
// TODO: handle multiple layers registered by same net module
|
||||
|
||||
// unregister all layers...
|
||||
// disable all layers...
|
||||
layer = g_layers.first;
|
||||
while (layer) {
|
||||
next = layer->next;
|
||||
@ -99,8 +108,12 @@ status_t stop_layers_manager()
|
||||
// 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);
|
||||
put_module(module_name);
|
||||
|
||||
layer = next;
|
||||
};
|
||||
|
||||
@ -114,39 +127,49 @@ status_t stop_layers_manager()
|
||||
// #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;
|
||||
module_info *dummy;
|
||||
net_layer *layer;
|
||||
|
||||
if (!layer)
|
||||
if (name == NULL ||
|
||||
strlen(name) <= 0 ||
|
||||
module == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
if (layer->module == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
layer = new_layer(name, module, cookie);
|
||||
if (!layer)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// 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)
|
||||
return status;
|
||||
goto error1;
|
||||
|
||||
layer->layers_above = NULL;
|
||||
layer->layers_below = NULL;
|
||||
|
||||
status = acquire_sem(g_layers.lock);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
goto error2;
|
||||
|
||||
layer->next = g_layers.first;
|
||||
g_layers.first = layer;
|
||||
|
||||
release_sem(g_layers.lock);
|
||||
|
||||
|
||||
printf("layers_manager: '%s' layer registered\n", layer->name);
|
||||
|
||||
if (_layer)
|
||||
*_layer = layer;
|
||||
return B_OK;
|
||||
|
||||
error2:
|
||||
put_module(module->info.name);
|
||||
error1:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
status_t unregister_layer(net_layer *layer)
|
||||
{
|
||||
@ -166,15 +189,57 @@ status_t unregister_layer(net_layer *layer)
|
||||
while (p && p->next != layer)
|
||||
p = p->next;
|
||||
|
||||
if (!p)
|
||||
if (!p) {
|
||||
// Oh oh... :-(
|
||||
printf("layers_manager: unregister_layer(): %p layer not found in list!\n", layer);
|
||||
else
|
||||
p->next = layer->next;
|
||||
release_sem(g_layers.lock);
|
||||
return B_ERROR;
|
||||
};
|
||||
|
||||
p->next = layer->next;
|
||||
};
|
||||
|
||||
release_sem(g_layers.lock);
|
||||
|
||||
layer->module->uninit(layer);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
net_layer *below;
|
||||
@ -244,27 +310,50 @@ status_t push_buffer_down(net_layer *layer, net_buffer *buffer)
|
||||
// #pragma mark [Private functions]
|
||||
|
||||
|
||||
#if 0
|
||||
// ----------------------------------------------------
|
||||
status_t interface_reader(void *args)
|
||||
// --------------------------------------------------
|
||||
static net_layer * new_layer(const char *name, net_layer_module_info *module, void *cookie)
|
||||
{
|
||||
ifnet_t *iface = args;
|
||||
net_buffer *buffer;
|
||||
status_t status;
|
||||
net_layer *layer;
|
||||
|
||||
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;
|
||||
|
||||
while(iface->if_flags & IFF_UP) {
|
||||
buffer = NULL;
|
||||
status = iface->module->receive_buffer(iface, &buffer);
|
||||
if (status < B_OK || buffer == NULL)
|
||||
continue;
|
||||
|
||||
dump_buffer(buffer);
|
||||
delete_buffer(buffer, false);
|
||||
};
|
||||
|
||||
return B_OK;
|
||||
if (layer->name)
|
||||
free(layer->name);
|
||||
if (layer->layers_above)
|
||||
free(layer->layers_above);
|
||||
if (layer->layers_below)
|
||||
free(layer->layers_below);
|
||||
|
||||
return g_memory_pool->delete_pool_node(g_layers_pool, layer);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef OBOS_NET_STACK_LAYERS_MANAGER_H
|
||||
#define OBOS_NET_STACK_LAYERS_MANAGER_H
|
||||
|
||||
#include "net_layer.h"
|
||||
#include "net_stack.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -14,9 +14,15 @@ extern "C" {
|
||||
extern status_t start_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 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_down(net_layer *me, struct net_buffer *buffer);
|
||||
|
||||
|
@ -73,6 +73,9 @@ struct net_stack_module_info nsmi = {
|
||||
// Layers handling
|
||||
register_layer,
|
||||
unregister_layer,
|
||||
add_layer_attribut,
|
||||
remove_layer_attribut,
|
||||
find_layer_attribut,
|
||||
|
||||
push_buffer_up,
|
||||
push_buffer_down,
|
||||
@ -91,6 +94,10 @@ struct net_stack_module_info nsmi = {
|
||||
|
||||
read_buffer,
|
||||
write_buffer,
|
||||
|
||||
add_buffer_attribut,
|
||||
remove_buffer_attribut,
|
||||
find_buffer_attribut,
|
||||
|
||||
dump_buffer,
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user