Moved ethernet and loopback "interface" module to new net_layer API.

Added an skeleton arp net layer.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3808 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2003-07-02 12:58:38 +00:00
parent 800e122ddc
commit 239aa01846
8 changed files with 300 additions and 192 deletions
+129
View File
@@ -0,0 +1,129 @@
/* ethernet.c - ethernet devices interface module
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/dirent.h>
#include <sys/stat.h>
#include <Drivers.h>
#include "net_stack.h"
#include "net_layer.h"
status_t std_ops(int32 op, ...);
struct net_layer_module_info nlmi;
static struct net_stack_module_info *g_stack = NULL;
// -------------------
status_t init(void * params)
{
status_t status;
net_layer *layer1, *layer2;
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;
}
status_t enable(net_layer *me, bool enable)
{
return B_OK;
}
status_t input_buffer(net_layer *me, net_buffer *buffer)
{
if (!buffer)
return B_ERROR;
// TODO!
return B_OK;
}
status_t output_buffer(net_layer *me, net_buffer *buffer)
{
if (!buffer)
return B_ERROR;
// TODO!
return B_OK;
}
// #pragma mark -
// #pragma mark -
status_t std_ops(int32 op, ...)
{
switch(op) {
case B_MODULE_INIT:
printf("arp: B_MODULE_INIT\n");
return get_module(NET_STACK_MODULE_NAME, (module_info **) &g_stack);
case B_MODULE_UNINIT:
printf("arp: B_MODULE_UNINIT\n");
put_module(NET_STACK_MODULE_NAME);
break;
default:
return B_ERROR;
}
return B_OK;
}
struct net_layer_module_info nlmi = {
{
NET_LAYER_MODULE_ROOT "protocols/arp/v0",
0,
std_ops
},
init,
uninit,
enable,
output_buffer,
input_buffer
};
_EXPORT module_info *modules[] = {
(module_info*) &nlmi, // net_layer_module_info
NULL
};
Binary file not shown.
+134 -108
View File
@@ -5,14 +5,16 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/dirent.h>
#include <sys/stat.h>
#include <KernelExport.h>
#include <Drivers.h>
#include "net_stack.h"
#include "net_interface.h"
#include "net_layer.h"
enum {
ETHER_GETADDR = B_DEVICE_OP_CODES_END,
@@ -24,11 +26,12 @@ enum {
ETHER_GETFRAMESIZE
};
typedef struct ethernet_interface {
ifnet_t ifnet;
int fd;
int max_frame_size;
} ethernet_interface;
typedef struct ethernet_device_layer {
net_layer layer;
int fd;
int max_frame_size;
volatile thread_id reader_thread;
} ethernet_device_layer;
#define ETHER_ADDR_LEN 6 /* Ethernet address length */
#define ETHER_TYPE_LEN 2 /* Ethernet type field length */
@@ -46,9 +49,10 @@ typedef struct ether_addr {
status_t lookup_devices(char *root, void *cookie);
status_t register_device(const char *path, void *cookie);
status_t device_reader(void *args);
status_t std_ops(int32 op, ...);
struct net_interface_module_info nimi;
struct net_layer_module_info nlmi;
static struct net_stack_module_info *g_stack = NULL;
@@ -59,92 +63,79 @@ status_t init(void * params)
return lookup_devices("/dev/net", params);
}
status_t uninit(ifnet_t *iface)
status_t uninit(net_layer *me)
{
ethernet_interface *ei = (ethernet_interface *) iface;
ethernet_device_layer *edl = (ethernet_device_layer *) me;
printf("ethernet: uniniting %s interface\n", iface->if_name);
printf("%s: uniniting layer\n", me->name);
free(iface->if_name);
close(ei->fd);
close(edl->fd);
free(me->name);
free(me);
return B_OK;
}
status_t up(ifnet_t *iface)
status_t enable(net_layer *me, bool enable)
{
return B_ERROR;
ethernet_device_layer *edl = (ethernet_device_layer *) me;
if (enable) {
// enable this layer
thread_id tid;
char name[B_OS_NAME_LENGTH * 2];
if (edl->reader_thread != -1)
// already up
return B_OK;
strncpy(name, me->name, sizeof(name));
strncat(name, " reader", sizeof(name));
tid = spawn_kernel_thread(device_reader, name, B_NORMAL_PRIORITY, me);
if (tid < 0) {
printf("%s: failed to start device reader thread -> %d [%s]\n",
me->name, (int) tid, strerror(tid));
return tid;
};
edl->reader_thread = tid;
return resume_thread(tid);
} else {
status_t dummy;
// disable this layer
if (edl->reader_thread == -1)
// already down
return B_OK;
send_signal_etc(edl->reader_thread, SIGTERM, 0);
wait_for_thread(edl->reader_thread, &dummy);
printf("%s: device reader stopped.\n", me->name);
edl->reader_thread = -1;
return B_OK;
};
return B_OK;
}
status_t down(ifnet_t *iface)
{
return B_ERROR;
}
status_t send(ifnet_t *iface, net_buffer *buffer)
status_t output_buffer(net_layer *me, net_buffer *buffer)
{
if (!buffer)
return B_ERROR;
// TODO!
return B_OK;
}
printf("%s: output_buffer:\n", me->name);
g_stack->dump_buffer(buffer);
status_t receive(ifnet_t *iface, net_buffer **received_buffer)
{
ethernet_interface *ei = (ethernet_interface *) iface;
net_buffer *buffer;
void *frame;
size_t len;
ssize_t sz;
len = iface->if_mtu;
frame = malloc(len);
if (!frame)
return B_NO_MEMORY;
buffer = g_stack->new_buffer();
if (!buffer) {
free(frame);
return B_NO_MEMORY;
};
sz = read(ei->fd, frame, len);
if (sz >= B_OK) {
g_stack->add_to_buffer(buffer, 0, frame, sz, (buffer_chunk_free_func) free);
*received_buffer = buffer;
return sz;
};
free(frame);
g_stack->delete_buffer(buffer, false);
return sz;
}
status_t control(ifnet_t *iface, int opcode, void *arg) { return -1; }
status_t get_hardware_address(ifnet_t *iface, net_interface_hwaddr *hwaddr) { return -1; }
status_t get_multicast_addresses(ifnet_t *iface, net_interface_hwaddr **hwaddr, int nb_addresses) { return -1; }
status_t set_multicast_addresses(ifnet_t *iface, net_interface_hwaddr *hwaddr, int nb_addresses) { return -1; }
status_t set_mtu(ifnet_t *iface, uint32 mtu)
{
ethernet_interface *ei = (ethernet_interface *) iface;
if (mtu > ei->max_frame_size)
// hardware constraint always win!
mtu = ei->max_frame_size;
ei->ifnet.if_mtu = mtu;
return B_OK;
}
status_t set_promiscuous(ifnet_t *iface, bool enable) { return -1; }
status_t set_media(ifnet_t *iface, uint32 media) { return -1; }
// #pragma mark -
@@ -178,8 +169,9 @@ status_t lookup_devices(char *root, void *cookie)
if (S_ISDIR(st.st_mode))
status = lookup_devices(path, cookie);
else if (S_ISCHR(st.st_mode)) { // char device = driver!
if (strcmp(de->d_name, "stack") == 0 || // OBOS stack driver
strcmp(de->d_name, "api") == 0) // BONE stack driver
if (strcmp(de->d_name, "stack") == 0 || // OBOS stack driver
strcmp(de->d_name, "server") == 0 || // OBOS server driver
strcmp(de->d_name, "api") == 0) // BONE stack driver
continue; // skip pseudo-entries
status = register_device(path, cookie);
@@ -194,16 +186,16 @@ status_t lookup_devices(char *root, void *cookie)
status_t register_device(const char *path, void *cookie)
{
ifnet_t *iface;
ethernet_interface *ei;
ethernet_device_layer *edl;
int frame_size;
ether_addr_t mac_address;
int fd;
status_t status;
char *name;
fd = open(path, O_RDWR);
if (fd < B_OK) {
printf("ethernet: Unable to open(%s) -> %d [%s]. Skipping...\n", path,
printf("ethernet: Unable to open %s device -> %d [%s]. Skipping...\n", path,
fd, strerror(fd));
return fd;
};
@@ -211,7 +203,7 @@ status_t register_device(const char *path, void *cookie)
// Init the network card
status = ioctl(fd, ETHER_INIT, NULL, 0);
if (status < B_OK) {
printf("ethernet: Failed to init %s: %ld [%s]. Skipping...\n", path,
printf("ethernet: Failed to init %s device -> %ld [%s]. Skipping...\n", path,
status, strerror(status));
close(fd);
return status;
@@ -220,7 +212,7 @@ status_t register_device(const char *path, void *cookie)
// get the MAC address...
status = ioctl(fd, ETHER_GETADDR, &mac_address, 6);
if (status < B_OK) {
printf("ethernet: Failed to get %s MAC address: %ld [%s]. Skipping...\n",
printf("ethernet: Failed to get %s device MAC address -> %ld [%s]. Skipping...\n",
path, status, strerror(status));
close(fd);
return status;
@@ -230,37 +222,79 @@ status_t register_device(const char *path, void *cookie)
status = ioctl(fd, ETHER_GETFRAMESIZE, &frame_size, sizeof(frame_size));
if (status < B_OK) {
frame_size = ETHERMTU;
printf("ethernet: %s device don't support IF_GETFRAMESIZE; defaulting to %d\n",
printf("ethernet: %s device don't support ETHER_GETFRAMESIZE; defaulting to %d\n",
path, frame_size);
};
printf("ethernet: interface '%s':\n"
"\tMAC address: %02x:%02x:%02x:%02x:%02x:%02x\n"
"\tMTU: %d bytes\n",
printf("ethernet: Found device '%s': MAC address: %02x:%02x:%02x:%02x:%02x:%02x, MTU: %d bytes\n",
path,
mac_address.byte[0], mac_address.byte[1],
mac_address.byte[2], mac_address.byte[3],
mac_address.byte[4], mac_address.byte[5], frame_size);
ei = (ethernet_interface *) malloc(sizeof(*ei));
if (!ei) {
edl = malloc(sizeof(*edl));
if (!edl) {
close(fd);
return B_NO_MEMORY;
};
ei->fd = fd;
ei->max_frame_size = frame_size;
edl->fd = fd;
edl->max_frame_size = frame_size;
edl->reader_thread = -1;
iface = &ei->ifnet;
name = malloc(strlen("ethernet/") + strlen(path));
strcpy(name, "ethernet/");
strcat(name, path + strlen("/dev/net/"));
iface->if_name = strdup(path);
iface->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
iface->if_type = 0x20; // IFT_ETHER;
iface->if_mtu = frame_size;
edl->layer.name = name;
edl->layer.module = &nlmi;
iface->module = &nimi;
return g_stack->register_layer(&edl->layer);
}
// ----------------------------------------------------
status_t device_reader(void *args)
{
net_layer *me = args;
ethernet_device_layer *edl = (ethernet_device_layer *) me;
net_buffer *buffer;
status_t status;
void *frame;
ssize_t sz;
printf("%s: device reader started.\n", me->name);
status = B_OK;
while(1) {
frame = malloc(edl->max_frame_size);
if (!frame) {
status = B_NO_MEMORY;
break;
};
// read on frame at time
sz = read(edl->fd, frame, edl->max_frame_size);
if (sz >= B_OK) {
buffer = g_stack->new_buffer();
if (!buffer) {
free(frame);
status = B_NO_MEMORY;
break;
};
g_stack->add_to_buffer(buffer, 0, frame, sz, (buffer_chunk_free_func) free);
return g_stack->register_interface(iface);
printf("%s: input buffer:\n", me->name);
g_stack->dump_buffer(buffer);
if (g_stack->push_buffer_up(me, buffer) != B_OK)
// nobody above us *eat* this buffer, so we drop it ourself :-(
g_stack->delete_buffer(buffer, false);
};
};
edl->reader_thread = -1;
return status;
}
// #pragma mark -
@@ -283,29 +317,21 @@ status_t std_ops(int32 op, ...)
return B_OK;
}
struct net_interface_module_info nimi = {
struct net_layer_module_info nlmi = {
{
NET_INTERFACE_MODULE_ROOT "ethernet/v0",
NET_LAYER_MODULE_ROOT "interfaces/ethernet",
0,
std_ops
},
init,
uninit,
up,
down,
send,
receive,
control,
get_hardware_address,
get_multicast_addresses,
set_multicast_addresses,
set_mtu,
set_promiscuous,
set_media
enable,
output_buffer,
NULL // interface layer: no input_buffer
};
_EXPORT module_info *modules[] = {
(module_info*) &nimi, // net_interface_module_info
(module_info*) &nlmi, // net_layer_module_info
NULL
};
@@ -1,102 +1,63 @@
/* loopback.c - loopback device
/* loopback.c - loopback interface module
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/dirent.h>
#include <sys/stat.h>
#include <Drivers.h>
#include "net_stack.h"
#include "net_interface.h"
#include "net_layer.h"
#define LOOPBACK_MTU 16384 // can be as large as we want
status_t std_ops(int32 op, ...);
struct net_layer_module_info nlmi;
static struct net_stack_module_info *g_stack = NULL;
typedef struct loopback_interface {
ifnet_t ifnet;
net_buffer_queue *queue;
} loopback_interface;
status_t std_ops(int32 op, ...);
struct net_interface_module_info nimi;
struct net_stack_module_info *g_stack = NULL;
// -------------------
status_t init(void * params)
{
ifnet_t * iface;
loopback_interface *li;
li = (loopback_interface *) malloc(sizeof(*li));
if (!li)
return B_NO_MEMORY;
net_layer *layer;
// create loopback fifo queue, to keep packets *sent*
li->queue = g_stack->new_buffer_queue(64*LOOPBACK_MTU);
layer = malloc(sizeof(*layer));
if (!layer)
return B_NO_MEMORY;
iface = &li->ifnet;
iface->if_name = "loopback";
iface->if_flags = (IFF_LOOPBACK | IFF_NOARP);
iface->if_type = 0x10; //IFT_LOOP
iface->if_mtu = LOOPBACK_MTU;
layer->name = "*/loopback";
layer->module = &nlmi;
// never forget to store a pointer to us, otherwise datalink layer can't call us
iface->module = &nimi;
return g_stack->register_interface(iface);
return g_stack->register_layer(layer);
}
status_t uninit(ifnet_t *iface)
status_t uninit(net_layer *me)
{
loopback_interface *li = (loopback_interface *) iface;
printf("loopback: uniniting %s interface\n", iface->if_name);
return g_stack->delete_buffer_queue(li->queue);
}
status_t up(ifnet_t *iface)
{
return B_ERROR;
printf("%s: uniniting layer\n", me->name);
free(me);
return B_OK;
}
status_t down(ifnet_t *iface)
status_t enable(net_layer *me, bool enable)
{
return B_ERROR;
return B_OK;
}
status_t send(ifnet_t *iface, net_buffer *buffer)
status_t output_buffer(net_layer *me, net_buffer *buffer)
{
loopback_interface *li = (loopback_interface *) iface;
if (!buffer)
return B_ERROR;
return g_stack->enqueue_buffer(li->queue, buffer);
return g_stack->push_buffer_up(me, buffer);
}
status_t receive(ifnet_t *iface, net_buffer **buffer)
{
loopback_interface *li = (loopback_interface *) iface;
return g_stack->dequeue_buffer(li->queue, buffer, B_INFINITE_TIMEOUT, false);
}
status_t control(ifnet_t *iface, int opcode, void *arg) { return -1; }
status_t get_hardware_address(ifnet_t *iface, net_interface_hwaddr *hwaddr) { return -1; }
status_t get_multicast_addresses(ifnet_t *iface, net_interface_hwaddr **hwaddr, int nb_addresses) { return -1; }
status_t set_multicast_addresses(ifnet_t *iface, net_interface_hwaddr *hwaddr, int nb_addresses) { return -1; }
status_t set_mtu(ifnet_t *iface, uint32 mtu) { return -1; }
status_t set_promiscuous(ifnet_t *iface, bool enable) { return -1; }
status_t set_media(ifnet_t *iface, uint32 media) { return -1; }
// #pragma mark -
status_t std_ops(int32 op, ...)
@@ -117,29 +78,21 @@ status_t std_ops(int32 op, ...)
return B_OK;
}
struct net_interface_module_info nimi = {
struct net_layer_module_info nlmi = {
{
NET_INTERFACE_MODULE_ROOT "loopback",
NET_LAYER_MODULE_ROOT "interfaces/loopback",
0,
std_ops
},
init,
uninit,
up,
down,
send,
receive,
control,
get_hardware_address,
get_multicast_addresses,
set_multicast_addresses,
set_mtu,
set_promiscuous,
set_media
enable,
output_buffer,
NULL // interface layer: no input_buffer
};
_EXPORT module_info *modules[] = {
(module_info*) &nimi, // net_interface_module_info
(module_info*) &nlmi, // net_layer_module_info
NULL
};