From 471d7380bd54c83cf6d090a144c288197b02db40 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 1 Feb 2010 15:13:08 +0100 Subject: check in libmachdev. --- libmachdev/net.c | 679 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 679 insertions(+) create mode 100644 libmachdev/net.c (limited to 'libmachdev/net.c') diff --git a/libmachdev/net.c b/libmachdev/net.c new file mode 100644 index 00000000..f14e9350 --- /dev/null +++ b/libmachdev/net.c @@ -0,0 +1,679 @@ +/* + * Linux network driver support. + * + * Copyright (C) 1996 The University of Utah and the Computer Systems + * Laboratory at the University of Utah (CSL) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Shantanu Goel, University of Utah CSL + */ + +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Ethernet-type device handling. + * + * Version: @(#)eth.c 1.0.7 05/25/93 + * + * Authors: Ross Biro, + * Fred N. van Kempen, + * Mark Evans, + * Florian La Roche, + * Alan Cox, + * + * Fixes: + * Mr Linux : Arp problems + * Alan Cox : Generic queue tidyup (very tiny here) + * Alan Cox : eth_header ntohs should be htons + * Alan Cox : eth_rebuild_header missing an htons and + * minor other things. + * Tegge : Arp bug fixes. + * Florian : Removed many unnecessary functions, code cleanup + * and changes for new arp and skbuff. + * Alan Cox : Redid header building to reflect new format. + * Alan Cox : ARP only when compiled with CONFIG_INET + * Greg Page : 802.2 and SNAP stuff. + * Alan Cox : MAC layer pointers/new format. + * Paul Gortmaker : eth_copy_and_sum shouldn't csum padding. + * Alan Cox : Protect against forwarding explosions with + * older network drivers and IFF_ALLMULTI + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include + +#include "mach_U.h" + +#include +#include + +#define MACH_INCLUDE + +#include "vm_param.h" +#include "device_reply_U.h" +#include "dev_hdr.h" +#include "if_ether.h" +#include "util.h" + +#define ether_header ethhdr + +extern int linux_intr_pri; +extern struct port_bucket *port_bucket; +extern struct port_class *dev_class; + +/* One of these is associated with each instance of a device. */ +struct net_data +{ + struct port_info port; /* device port */ +// struct ifnet ifnet; /* Mach ifnet structure (needed for filters) */ + struct emul_device device; /* generic device structure */ + mach_port_t delivery_port; + struct net_device *dev; /* Linux network device structure */ + struct net_data *next; +}; + +struct skb_reply +{ + mach_port_t reply; + mach_msg_type_name_t reply_type; + int pkglen; +}; + +struct sk_buff; +void skb_done_queue(struct sk_buff *skb); +struct sk_buff *skb_done_dequeue(); +void linux_net_emulation_init (); +void *skb_reply(struct sk_buff *skb); +int netdev_flags(struct net_device *dev); +char *netdev_addr(struct net_device *dev); +int dev_change_flags (struct net_device *dev, short flags); +int linux_pkg_xmit (char *pkg_data, int len, void *del_data, + int (*del_func) (struct sk_buff *, void *), + struct net_device *dev); +struct net_device *search_netdev (char *name); +void kfree_skb (struct sk_buff *skb); +int dev_open(struct net_device *dev); +void *l4dde26_register_rx_callback(void *cb); +void skb_done_head_init(); + +struct net_data *nd_head; + +/* Forward declarations. */ + +extern struct device_emulation_ops linux_net_emulation_ops; + +static int print_packet_size = 0; + +mach_msg_type_t header_type = +{ + MACH_MSG_TYPE_BYTE, + 8, + NET_HDW_HDR_MAX, + TRUE, + FALSE, + FALSE, + 0 +}; + +mach_msg_type_t packet_type = +{ + MACH_MSG_TYPE_BYTE, /* name */ + 8, /* size */ + 0, /* number */ + TRUE, /* inline */ + FALSE, /* longform */ + FALSE /* deallocate */ +}; + +struct net_data *search_nd (struct net_device *dev) +{ + struct net_data *nd = nd_head; + + //TODO protected by locks. + while (nd) + { + if (nd->dev == dev) + return nd; + nd = nd->next; + } + return NULL; +} + +/* Linux kernel network support routines. */ + +/* Free all sk_buffs on the done list. + This routine is called by the iodone thread in ds_routines.c. */ +void +free_skbuffs () +{ + struct sk_buff *skb; + + while (1) + { + skb = skb_done_dequeue (); + if (skb) + { + struct skb_reply *reply = skb_reply(skb); + if (MACH_PORT_VALID (reply->reply)) + { + ds_device_write_reply (reply->reply, reply->reply_type, + 0, reply->pkglen); + reply->reply = MACH_PORT_NULL; + } + kfree_skb (skb); + } + else + break; + } +} + +/* actions before freeing the sk_buff SKB. + * If it returns 1, the packet will be deallocated later. */ +int +pre_kfree_skb (struct sk_buff *skb, void *data) +{ + struct skb_reply *reply = data; + extern void wakeup_io_done_thread (); + + /* Queue sk_buff on done list if there is a + page list attached or we need to send a reply. + Wakeup the iodone thread to process the list. */ + if (reply && MACH_PORT_VALID (reply->reply)) + { + skb_done_queue (skb); + wakeup_io_done_thread (); + return 1; + } + return 0; +} + +/* + * Deliver the message to all right pfinet servers that + * connects to the virtual network interface. + */ +int +deliver_msg(mach_port_t dest, struct net_rcv_msg *msg) +{ + mach_msg_return_t err; + + msg->msg_hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); + /* remember message sizes must be rounded up */ + msg->msg_hdr.msgh_local_port = MACH_PORT_NULL; + msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL; + msg->msg_hdr.msgh_id = NET_RCV_MSG_ID; + + msg->msg_hdr.msgh_remote_port = dest; + err = mach_msg ((mach_msg_header_t *)msg, + MACH_SEND_MSG|MACH_SEND_TIMEOUT, + msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL, + 0, MACH_PORT_NULL); + if (err != MACH_MSG_SUCCESS) + { + mach_port_deallocate(mach_task_self (), + ((mach_msg_header_t *)msg)->msgh_remote_port); + return err; + } + + return MACH_MSG_SUCCESS; +} + +/* Accept packet SKB received on an interface. */ +void +netif_rx_handle (char *data, int len, struct net_device *dev) +{ + int pack_size; + net_rcv_msg_t net_msg; + struct ether_header *eh; + struct packet_header *ph; + struct net_data *nd; + + if (print_packet_size) + printf ("netif_rx: length %d\n", len); + + nd = search_nd(dev); + assert (nd); + + /* Allocate a kernel message buffer. */ + net_msg = malloc (sizeof (*net_msg)); + if (!net_msg) + return; + + pack_size = len - sizeof (struct ethhdr); + /* remember message sizes must be rounded up */ + net_msg->msg_hdr.msgh_size = (((mach_msg_size_t) (sizeof(struct net_rcv_msg) + - NET_RCV_MAX + pack_size)) + 3) & ~3; + + /* Copy packet into message buffer. */ + eh = (struct ether_header *) (net_msg->header); + ph = (struct packet_header *) (net_msg->packet); + memcpy (eh, data, sizeof (struct ether_header)); + /* packet is prefixed with a struct packet_header, + see include/device/net_status.h. */ + memcpy (ph + 1, data + sizeof (struct ether_header), pack_size); + ph->type = eh->h_proto; + ph->length = pack_size + sizeof (struct packet_header); + + net_msg->sent = FALSE; /* Mark packet as received. */ + + net_msg->header_type = header_type; + net_msg->packet_type = packet_type; + net_msg->net_rcv_msg_packet_count = ph->length; + deliver_msg (nd->delivery_port, net_msg); + free (net_msg); +} + +/* Mach device interface routines. */ + +/* Return a send right associated with network device ND. */ +static mach_port_t +dev_to_port (void *nd) +{ + return (nd + ? ports_get_send_right (nd) + : MACH_PORT_NULL); +} + +#if 0 +/* + * Initialize send and receive queues on an interface. + */ +void if_init_queues(ifp) + register struct ifnet *ifp; +{ + IFQ_INIT(&ifp->if_snd); + queue_init(&ifp->if_rcv_port_list); + queue_init(&ifp->if_snd_port_list); + simple_lock_init(&ifp->if_rcv_port_list_lock); + simple_lock_init(&ifp->if_snd_port_list_lock); +} +#endif + +static io_return_t +device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, + dev_mode_t mode, char *name, device_t *devp) +{ + io_return_t err = D_SUCCESS; + struct net_device *dev; + struct net_data *nd; +// struct ifnet *ifp; + + /* Search for the device. */ + dev = search_netdev (name); + if (!dev) + return D_NO_SUCH_DEVICE; + + /* Allocate and initialize device data if this is the first open. */ + nd = search_nd (dev); + if (!nd) + { + err = ports_create_port (dev_class, port_bucket, + sizeof (*nd), &nd); + if (err) + goto out; + + nd->dev = dev; + nd->device.emul_data = nd; + nd->device.emul_ops = &linux_net_emulation_ops; + nd->next = nd_head; + nd_head = nd; +#if 0 + ipc_kobject_set (nd->port, (ipc_kobject_t) & nd->device, IKOT_DEVICE); + notify = ipc_port_make_sonce (nd->port); + ip_lock (nd->port); + ipc_port_nsrequest (nd->port, 1, notify, ¬ify); + assert (notify == IP_NULL); + + ifp = &nd->ifnet; + ifp->if_unit = dev->name[strlen (dev->name) - 1] - '0'; + ifp->if_flags = IFF_UP | IFF_RUNNING; + ifp->if_mtu = dev->mtu; + ifp->if_header_size = dev->hard_header_len; + ifp->if_header_format = dev->type; + ifp->if_address_size = dev->addr_len; + ifp->if_address = dev->dev_addr; + if_init_queues (ifp); +#endif + + if (dev_open(dev) < 0) + err = D_NO_SUCH_DEVICE; + + out: + if (err) + { + if (nd) + { + ports_destroy_right (nd); + nd = NULL; + } + } + else + { +#if 0 + /* IPv6 heavily relies on multicasting (especially router and + neighbor solicits and advertisements), so enable reception of + those multicast packets by setting `LINUX_IFF_ALLMULTI'. */ + dev->flags |= LINUX_IFF_UP | LINUX_IFF_RUNNING | LINUX_IFF_ALLMULTI; + skb_queue_head_init (&dev->buffs[0]); + + if (dev->set_multicast_list) + dev->set_multicast_list (dev); +#endif + } + if (MACH_PORT_VALID (reply_port)) + ds_device_open_reply (reply_port, reply_port_type, + err, dev_to_port (nd)); + return MIG_NO_REPLY; + } + + *devp = ports_get_right (nd); + return D_SUCCESS; +} + +static io_return_t +device_write (void *d, mach_port_t reply_port, + mach_msg_type_name_t reply_port_type, dev_mode_t mode, + recnum_t bn, io_buf_ptr_t data, unsigned int count, + int *bytes_written) +{ + struct net_data *nd = d; + struct net_device *dev = nd->dev; + struct skb_reply *skb_reply = malloc (sizeof (*skb_reply)); + + if (skb_reply == NULL) + return D_NO_MEMORY; + + skb_reply->pkglen = count; + skb_reply->reply = reply_port; + skb_reply->reply_type = reply_port_type; + + linux_pkg_xmit (data, count, skb_reply, pre_kfree_skb, dev); + vm_deallocate (mach_task_self (), (vm_address_t) data, count); + + /* Send packet to filters. */ + // TODO should I deliver the packet to other network stacks? +#if 0 + { + struct packet_header *packet; + struct ether_header *header; + ipc_kmsg_t kmsg; + + kmsg = net_kmsg_get (); + + if (kmsg != IKM_NULL) + { + /* Suitable for Ethernet only. */ + header = (struct ether_header *) (net_kmsg (kmsg)->header); + packet = (struct packet_header *) (net_kmsg (kmsg)->packet); + memcpy (header, skb->data, sizeof (struct ether_header)); + + /* packet is prefixed with a struct packet_header, + see include/device/net_status.h. */ + memcpy (packet + 1, skb->data + sizeof (struct ether_header), + skb->len - sizeof (struct ether_header)); + packet->length = skb->len - sizeof (struct ether_header) + + sizeof (struct packet_header); + packet->type = header->ether_type; + net_kmsg (kmsg)->sent = TRUE; /* Mark packet as sent. */ + s = splimp (); + net_packet (&dev->net_data->ifnet, kmsg, packet->length, + ethernet_priority (kmsg)); + splx (s); + } + } +#endif + + return MIG_NO_REPLY; +} + +/* + * Other network operations + */ +io_return_t +net_getstat(dev, flavor, status, count) + struct net_device *dev; + dev_flavor_t flavor; + dev_status_t status; /* pointer to OUT array */ + natural_t *count; /* OUT */ +{ +#define ETHERMTU 1500 + switch (flavor) { + case NET_STATUS: + { + register struct net_status *ns = (struct net_status *)status; + + if (*count < NET_STATUS_COUNT) + return (D_INVALID_OPERATION); + + ns->min_packet_size = 60; + ns->max_packet_size = ETH_HLEN + ETHERMTU; + ns->header_format = HDR_ETHERNET; + ns->header_size = ETH_HLEN; + ns->address_size = ETH_ALEN; + ns->flags = 0; + ns->mapped_size = 0; + + *count = NET_STATUS_COUNT; + break; + } + case NET_ADDRESS: + { + register int addr_byte_count; + register int addr_int_count; + register int i; + + addr_byte_count = ETH_ALEN; + addr_int_count = (addr_byte_count + (sizeof(int)-1)) + / sizeof(int); + + if (*count < addr_int_count) + { + /* XXX debug hack. */ + printf ("net_getstat: count: %d, addr_int_count: %d\n", + *count, addr_int_count); + return (D_INVALID_OPERATION); + } + + memcpy(status, netdev_addr(dev), addr_byte_count); + if (addr_byte_count < addr_int_count * sizeof(int)) + memset((char *)status + addr_byte_count, 0, + (addr_int_count * sizeof(int) + - addr_byte_count)); + + for (i = 0; i < addr_int_count; i++) { + register int word; + + word = status[i]; + status[i] = htonl(word); + } + *count = addr_int_count; + break; + } + default: + return (D_INVALID_OPERATION); + } + return (D_SUCCESS); +} + +static io_return_t +device_get_status (void *d, dev_flavor_t flavor, dev_status_t status, + mach_msg_type_number_t *count) +{ + struct net_data *net = (struct net_data *) d; + + if (flavor == NET_FLAGS) + { + if (*count != sizeof(short)) + return D_INVALID_SIZE; + + *(short *) status = netdev_flags (net->dev); + return D_SUCCESS; + } + +#if 0 + if(flavor >= SIOCIWFIRST && flavor <= SIOCIWLAST) + { + /* handle wireless ioctl */ + if(! IW_IS_GET(flavor)) + return D_INVALID_OPERATION; + + if(*count * sizeof(int) < sizeof(struct ifreq)) + return D_INVALID_OPERATION; + + struct net_data *nd = d; + struct linux_device *dev = nd->dev; + + if(! dev->do_ioctl) + return D_INVALID_OPERATION; + + int result; + + if (flavor == SIOCGIWRANGE || flavor == SIOCGIWENCODE + || flavor == SIOCGIWESSID || flavor == SIOCGIWNICKN + || flavor == SIOCGIWSPY) + { + /* + * These ioctls require an `iw_point' as their argument (i.e. + * they want to return some data to userspace. + * Therefore supply some sane values and carry the data back + * to userspace right behind the `struct iwreq'. + */ + struct iw_point *iwp = &((struct iwreq *) status)->u.data; + iwp->length = *count * sizeof (dev_status_t) - sizeof (struct ifreq); + iwp->pointer = (void *) status + sizeof (struct ifreq); + + result = dev->do_ioctl (dev, (struct ifreq *) status, flavor); + + *count = ((sizeof (struct ifreq) + iwp->length) + / sizeof (dev_status_t)); + if (iwp->length % sizeof (dev_status_t)) + (*count) ++; + } + else + { + *count = sizeof(struct ifreq) / sizeof(int); + result = dev->do_ioctl(dev, (struct ifreq *) status, flavor); + } + + return result ? D_IO_ERROR : D_SUCCESS; + } + else +#endif + { + /* common get_status request */ + return net_getstat (net->dev, flavor, status, count); + } +} + +static io_return_t +device_set_status(void *d, dev_flavor_t flavor, dev_status_t status, + mach_msg_type_number_t count) +{ + if (flavor == NET_FLAGS) + { + if (count != sizeof(short)) + return D_INVALID_SIZE; + + short flags = *(short *) status; + struct net_data *net = (struct net_data *) d; + + dev_change_flags (net->dev, flags); + + return D_SUCCESS; + } + return D_INVALID_OPERATION; + +#if 0 + if(flavor < SIOCIWFIRST || flavor > SIOCIWLAST) + return D_INVALID_OPERATION; + + if(! IW_IS_SET(flavor)) + return D_INVALID_OPERATION; + + if(count * sizeof(int) < sizeof(struct ifreq)) + return D_INVALID_OPERATION; + + struct net_data *nd = d; + struct linux_device *dev = nd->dev; + + if(! dev->do_ioctl) + return D_INVALID_OPERATION; + + if((flavor == SIOCSIWENCODE || flavor == SIOCSIWESSID + || flavor == SIOCSIWNICKN || flavor == SIOCSIWSPY) + && ((struct iwreq *) status)->u.data.pointer) + { + struct iw_point *iwp = &((struct iwreq *) status)->u.data; + + /* safety check whether the status array is long enough ... */ + if(count * sizeof(int) < sizeof(struct ifreq) + iwp->length) + return D_INVALID_OPERATION; + + /* make sure, iwp->pointer points to the correct address */ + if(iwp->pointer) iwp->pointer = (void *) status + sizeof(struct ifreq); + } + + int result = dev->do_ioctl(dev, (struct ifreq *) status, flavor); + return result ? D_IO_ERROR : D_SUCCESS; +#endif +} + + +static io_return_t +device_set_filter (void *d, mach_port_t port, int priority, + filter_t * filter, unsigned filter_count) +{ + ((struct net_data *) d)->delivery_port = port; + return 0; +#if 0 + return net_set_filter (&((struct net_data *) d)->ifnet, + port, priority, filter, filter_count); +#endif +} + +/* Do any initialization required for network devices. */ +void linux_net_emulation_init () +{ + skb_done_head_init(); + l4dde26_register_rx_callback(netif_rx_handle); +} + +struct device_emulation_ops linux_net_emulation_ops = +{ + linux_net_emulation_init, + NULL, + NULL, + dev_to_port, + device_open, + NULL, + device_write, + NULL, + NULL, + NULL, + device_set_status, + device_get_status, + device_set_filter, + NULL, + NULL, + NULL, + NULL +}; -- cgit v1.2.3 From cdc836f8e3eee674d34224474cb8b36363bac2a7 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 5 Feb 2010 15:08:38 +0100 Subject: create device port with create_device_port. --- libmachdev/net.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'libmachdev/net.c') diff --git a/libmachdev/net.c b/libmachdev/net.c index f14e9350..0571547c 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -326,8 +326,7 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, nd = search_nd (dev); if (!nd) { - err = ports_create_port (dev_class, port_bucket, - sizeof (*nd), &nd); + err = create_device_port (sizeof (*nd), &nd); if (err) goto out; -- cgit v1.2.3 From ac029a4bf4fe508d7cebbaa7c55fcba64e2d6726 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 5 Feb 2010 15:10:35 +0100 Subject: deallocate skb_reply before freeing the packet. --- libmachdev/net.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libmachdev/net.c') diff --git a/libmachdev/net.c b/libmachdev/net.c index 0571547c..8e579e58 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -204,6 +204,8 @@ pre_kfree_skb (struct sk_buff *skb, void *data) wakeup_io_done_thread (); return 1; } + /* deallocate skb_reply before freeing the packet. */ + free (data); return 0; } -- cgit v1.2.3 From aff295710ea0b575c556f10981d1ae740e192969 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 8 Feb 2010 06:52:59 +0100 Subject: return packet transmission error to the client. --- libmachdev/net.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'libmachdev/net.c') diff --git a/libmachdev/net.c b/libmachdev/net.c index 8e579e58..d80e86ff 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -399,6 +399,7 @@ device_write (void *d, mach_port_t reply_port, struct net_data *nd = d; struct net_device *dev = nd->dev; struct skb_reply *skb_reply = malloc (sizeof (*skb_reply)); + error_t err; if (skb_reply == NULL) return D_NO_MEMORY; @@ -407,8 +408,10 @@ device_write (void *d, mach_port_t reply_port, skb_reply->reply = reply_port; skb_reply->reply_type = reply_port_type; - linux_pkg_xmit (data, count, skb_reply, pre_kfree_skb, dev); + err = linux_pkg_xmit (data, count, skb_reply, pre_kfree_skb, dev); vm_deallocate (mach_task_self (), (vm_address_t) data, count); + if (err) + return err; /* Send packet to filters. */ // TODO should I deliver the packet to other network stacks? -- cgit v1.2.3 From 5ea9105dff5f22606026afcd88b178110282b224 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 8 Feb 2010 08:58:53 +0100 Subject: remove io done thread. eliminate a potential race condition in thread_wait and thread_wakeup. --- libmachdev/ds_routines.c | 362 ----------------------------------------------- libmachdev/net.c | 35 +---- 2 files changed, 6 insertions(+), 391 deletions(-) (limited to 'libmachdev/net.c') diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index c647b8e9..857f64c5 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -448,362 +448,6 @@ ds_device_map (device_t dev, vm_prot_t prot, vm_offset_t offset, return D_INVALID_OPERATION; } -boolean_t -ds_open_done(ior) - register io_req_t ior; -{ - kern_return_t result; - register mach_device_t device; - - device = ior->io_device; - result = ior->io_error; - - if (result != D_SUCCESS) { - /* - * Open failed. Deallocate port and device. - */ -// dev_port_remove(device); -// ipc_port_dealloc_kernel(device->port); - - device_lock(device); - device->state = DEV_STATE_INIT; - if (device->io_wait) { - device->io_wait = FALSE; -// thread_wakeup((event_t)device); - } - device_unlock(device); - -// mach_device_deallocate(device); - device = MACH_DEVICE_NULL; - } - else { - /* - * Open succeeded. - */ - device_lock(device); - device->state = DEV_STATE_OPEN; - device->open_count = 1; - if (device->io_wait) { - device->io_wait = FALSE; -// thread_wakeup((event_t)device); - } - device_unlock(device); - - /* donate device reference to get port */ - } - /* - * Must explicitly convert device to port, since - * device_reply interface is built as 'user' side - * (thus cannot get translation). - */ - if (MACH_PORT_VALID(ior->io_reply_port)) { - (void) ds_device_open_reply(ior->io_reply_port, - ior->io_reply_port_type, - result, - mach_convert_device_to_port(device)); - } -// else -// mach_device_deallocate(device); - - mach_device_deallocate (device); - return (TRUE); -} - -boolean_t ds_read_done(ior) - io_req_t ior; -{ - vm_offset_t start_data, end_data; - vm_offset_t start_sent, end_sent; - register vm_size_t size_read; - - if (ior->io_error) - size_read = 0; - else - size_read = ior->io_count - ior->io_residual; - - start_data = (vm_offset_t)ior->io_data; - end_data = start_data + size_read; - - start_sent = (ior->io_op & IO_INBAND) ? start_data : - trunc_page(start_data); - end_sent = (ior->io_op & IO_INBAND) ? - start_data + ior->io_alloc_size : round_page(end_data); - - /* - * Zero memory that the device did not fill. - */ - if (start_sent < start_data) - memset((char *)start_sent, 0, start_data - start_sent); - if (end_sent > end_data) - memset((char *)end_data, 0, end_sent - end_data); - - - /* - * Touch the data being returned, to mark it dirty. - * If the pages were filled by DMA, the pmap module - * may think that they are clean. - */ - { - register vm_offset_t touch; - register int c; - - for (touch = start_sent; touch < end_sent; touch += PAGE_SIZE) { - c = *(volatile char *)touch; - *(volatile char *)touch = c; - } - } - - /* - * Send the data to the reply port - this - * unwires and deallocates it. - */ - if (ior->io_op & IO_INBAND) { - (void)ds_device_read_reply_inband(ior->io_reply_port, - ior->io_reply_port_type, - ior->io_error, - (char *) start_data, - size_read); - } else { -// vm_map_copy_t copy; -// kern_return_t kr; -// -// kr = vm_map_copyin_page_list(kernel_map, start_data, -// size_read, TRUE, TRUE, -// ©, FALSE); -// -// if (kr != KERN_SUCCESS) -// panic("read_done: vm_map_copyin_page_list failed"); - - (void)ds_device_read_reply(ior->io_reply_port, - ior->io_reply_port_type, - ior->io_error, - (char *) start_data, - size_read); - } - - /* - * Free any memory that was allocated but not sent. - */ - if (ior->io_count != 0) { - if (ior->io_op & IO_INBAND) { - if (ior->io_alloc_size > 0) - free (ior->io_data); -// zfree(io_inband_zone, (vm_offset_t)ior->io_data); - } else { - register vm_offset_t end_alloc; - - end_alloc = start_sent + round_page(ior->io_alloc_size); - if (end_alloc > end_sent) - vm_deallocate(mach_task_self (), - end_sent, - end_alloc - end_sent); - } - } - - mach_device_deallocate(ior->io_device); - - return (TRUE); -} - -/* - * Allocate wired-down memory for device read. - */ -kern_return_t device_read_alloc(ior, size) - register io_req_t ior; - register vm_size_t size; -{ - vm_offset_t addr; - kern_return_t kr; - - /* - * Nothing to do if no data. - */ - if (ior->io_count == 0) - return (KERN_SUCCESS); - - if (ior->io_op & IO_INBAND) { - ior->io_data = (io_buf_ptr_t) malloc(sizeof(io_buf_ptr_inband_t)); - ior->io_alloc_size = sizeof(io_buf_ptr_inband_t); - } else { - size = round_page(size); - kr = vm_allocate (mach_task_self (), &addr, size, TRUE); -// kr = kmem_alloc(kernel_map, &addr, size); - if (kr != KERN_SUCCESS) - return (kr); - - ior->io_data = (io_buf_ptr_t) addr; - ior->io_alloc_size = size; - } - - return (KERN_SUCCESS); -} - -struct thread_wait -{ - struct condition cond; - struct mutex mutex; - int v; -}; - -static struct thread_wait io_done_wait; - -void thread_wait_init (struct thread_wait *t) -{ - mutex_init (&t->mutex); - condition_init (&t->cond); - t->v = 0; -} - -void thread_block (struct thread_wait *t) -{ - mutex_lock (&t->mutex); - t->v = 1; - while (t->v) - hurd_condition_wait (&t->cond, &t->mutex); - mutex_unlock (&t->mutex); -} - -void thread_wakeup (struct thread_wait *t) -{ - mutex_lock (&t->mutex); - t->v = 0; - condition_signal (&t->cond); - mutex_unlock (&t->mutex); -} - -queue_head_t io_done_list; -struct mutex io_done_list_lock; - -#define splio splsched /* XXX must block ALL io devices */ - -void iodone(ior) - register io_req_t ior; -{ - /* - * If this ior was loaned to us, return it directly. - */ - if (ior->io_op & IO_LOANED) { - (*ior->io_done)(ior); - return; - } - /* - * If !IO_CALL, some thread is waiting for this. Must lock - * structure to interlock correctly with iowait(). Else can - * toss on queue for io_done thread to call completion. - */ - // TODO need a lock here? -// s = splio(); - if ((ior->io_op & IO_CALL) == 0) { - ior_lock(ior); - ior->io_op |= IO_DONE; - ior->io_op &= ~IO_WANTED; - ior_unlock(ior); -// thread_wakeup((event_t)ior); - } else { - ior->io_op |= IO_DONE; - mutex_lock (&io_done_list_lock); - enqueue_tail(&io_done_list, (queue_entry_t)ior); - thread_wakeup (&io_done_wait); -// thread_wakeup((event_t)&io_done_list); - mutex_unlock (&io_done_list_lock); - } -// splx(s); -} - -void wakeup_io_done_thread () -{ - thread_wakeup (&io_done_wait); -} - -void io_done_thread_continue() -{ - for (;;) { - extern void free_skbuffs (); - register io_req_t ior; - - free_skbuffs (); - mutex_lock(&io_done_list_lock); - while ((ior = (io_req_t)dequeue_head(&io_done_list)) != 0) { - mutex_unlock(&io_done_list_lock); - - if ((*ior->io_done)(ior)) { - /* - * IO done - free io_req_elt - */ - io_req_free(ior); - } - /* else routine has re-queued it somewhere */ - - mutex_lock(&io_done_list_lock); - } - -// assert_wait(&io_done_list, FALSE); - mutex_unlock(&io_done_list_lock); -// counter(c_io_done_thread_block++); -// thread_block(io_done_thread_continue); - thread_block (&io_done_wait); - } -} - - -void -wire_thread() -{ - kern_return_t kr; - mach_port_t priv_host_port; - - kr = get_privileged_ports (&priv_host_port, NULL); - if (kr != KERN_SUCCESS) - panic("get privileged port: %d", kr); - - kr = thread_wire(priv_host_port, - mach_thread_self(), - TRUE); - if (kr != KERN_SUCCESS) - panic("wire_thread: %d", kr); -} - -void -thread_set_own_priority (int priority) -{ - kern_return_t kr; - mach_port_t priv_host_port; - mach_port_t pset, psetcntl; - - kr = get_privileged_ports (&priv_host_port, NULL); - if (kr != KERN_SUCCESS) - panic("get privileged port: %d", kr); - - kr = thread_get_assignment (mach_thread_self (), &pset); - if (kr != KERN_SUCCESS) - panic("thread get assignment: %d", kr); - kr = host_processor_set_priv (priv_host_port, pset, &psetcntl); - if (kr != KERN_SUCCESS) - panic("processor set priv: %d", kr); - kr = thread_max_priority (mach_thread_self (), psetcntl, 0); - if (kr != KERN_SUCCESS) - panic("set thread max priority: %d", kr); - kr = thread_priority (mach_thread_self (), 0, FALSE); - if (kr != KERN_SUCCESS) - panic("set thread priority: %d", kr); -} - -static any_t io_done_thread(any_t unused) -{ - /* - * Set thread privileges and highest priority. - */ -// current_thread()->vm_privilege = TRUE; -// stack_privilege(current_thread()); - wire_thread (); - - thread_set_own_priority(0); - - io_done_thread_continue(); - /*NOTREACHED*/ - return 0; -} - int create_device_port (int size, void *result) { return ports_create_port (dev_class, port_bucket, @@ -814,18 +458,12 @@ void mach_device_init() { int i; - queue_init(&io_done_list); - mutex_init (&io_done_list_lock); - thread_wait_init (&io_done_wait); - port_bucket = ports_create_bucket (); dev_class = ports_create_class (0, 0); for (i = 0; i < NUM_EMULATION; i++) { emulation_list[i]->init(); } - - cthread_detach (cthread_fork (io_done_thread, 0)); } static int diff --git a/libmachdev/net.c b/libmachdev/net.c index d80e86ff..9a367a6b 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -161,32 +161,6 @@ struct net_data *search_nd (struct net_device *dev) /* Linux kernel network support routines. */ -/* Free all sk_buffs on the done list. - This routine is called by the iodone thread in ds_routines.c. */ -void -free_skbuffs () -{ - struct sk_buff *skb; - - while (1) - { - skb = skb_done_dequeue (); - if (skb) - { - struct skb_reply *reply = skb_reply(skb); - if (MACH_PORT_VALID (reply->reply)) - { - ds_device_write_reply (reply->reply, reply->reply_type, - 0, reply->pkglen); - reply->reply = MACH_PORT_NULL; - } - kfree_skb (skb); - } - else - break; - } -} - /* actions before freeing the sk_buff SKB. * If it returns 1, the packet will be deallocated later. */ int @@ -200,9 +174,12 @@ pre_kfree_skb (struct sk_buff *skb, void *data) Wakeup the iodone thread to process the list. */ if (reply && MACH_PORT_VALID (reply->reply)) { - skb_done_queue (skb); - wakeup_io_done_thread (); - return 1; + if (MACH_PORT_VALID (reply->reply)) + { + ds_device_write_reply (reply->reply, reply->reply_type, + 0, reply->pkglen); + reply->reply = MACH_PORT_NULL; + } } /* deallocate skb_reply before freeing the packet. */ free (data); -- cgit v1.2.3 From 045fb6a578e0e4d97f0e581bbf514654686a86c1 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Tue, 4 May 2010 15:56:46 +0200 Subject: Add printing. --- dde_e1000/e1000_hw.c | 3 +++ dde_e1000/e1000_main.c | 33 ++++++++++++++++++++++++++++++-- libdde_linux26/lib/src/arch/l4/kmalloc.c | 11 ++++++++++- libdde_linux26/lib/src/arch/l4/res.c | 8 ++++++++ libdde_linux26/lib/src/net/core/skbuff.c | 9 +++++++-- libmachdev/net.c | 17 ++++++++++++---- 6 files changed, 72 insertions(+), 9 deletions(-) (limited to 'libmachdev/net.c') diff --git a/dde_e1000/e1000_hw.c b/dde_e1000/e1000_hw.c index e1a3fc13..27ed37d4 100644 --- a/dde_e1000/e1000_hw.c +++ b/dde_e1000/e1000_hw.c @@ -5627,6 +5627,7 @@ s32 e1000_read_mac_addr(struct e1000_hw *hw) DEBUGFUNC("e1000_read_mac_addr"); + printk("mac address: "); for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { offset = i >> 1; if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { @@ -5635,7 +5636,9 @@ s32 e1000_read_mac_addr(struct e1000_hw *hw) } hw->perm_mac_addr[i] = (u8)(eeprom_data & 0x00FF); hw->perm_mac_addr[i+1] = (u8)(eeprom_data >> 8); + printk("%x%x ", hw->perm_mac_addr[i], hw->perm_mac_addr[i+1]); } + printk("\n"); switch (hw->mac_type) { default: diff --git a/dde_e1000/e1000_main.c b/dde_e1000/e1000_main.c index f25a5367..3f608476 100644 --- a/dde_e1000/e1000_main.c +++ b/dde_e1000/e1000_main.c @@ -328,13 +328,15 @@ static void e1000_update_mng_vlan(struct e1000_adapter *adapter) E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { e1000_vlan_rx_add_vid(netdev, vid); adapter->mng_vlan_id = vid; - } else + } else { adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; + } if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && (vid != old_vid) && - !vlan_group_get_device(adapter->vlgrp, old_vid)) + !vlan_group_get_device(adapter->vlgrp, old_vid)) { e1000_vlan_rx_kill_vid(netdev, old_vid); + } } else adapter->mng_vlan_id = vid; } @@ -937,7 +939,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* do not allocate ioport bars when not needed */ need_ioport = e1000_is_need_ioport(pdev); + printk("do we need ioport? %d\n", need_ioport); if (need_ioport) { + printk("pci_enable_device will be called\n"); bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO); err = pci_enable_device(pdev); } else { @@ -947,6 +951,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (err) return err; + printk("bars: %x\n", bars); if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { pci_using_dac = 1; @@ -998,6 +1003,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, continue; if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { hw->io_base = pci_resource_start(pdev, i); + printk("io base: %p, i: %d\n", + hw->io_base, i); break; } } @@ -1084,6 +1091,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, */ memset(hw->mac_addr, 0, netdev->addr_len); } else { + printk("succeed to validate eeprom\n"); /* copy the MAC address out of the EEPROM */ if (e1000_read_mac_addr(hw)) DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); @@ -1585,6 +1593,8 @@ static int e1000_setup_tx_resources(struct e1000_adapter *adapter, txdr->size = ALIGN(txdr->size, 4096); txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); + printk("allocate %d bytes for transmit desc ring: %p\n", + txdr->size, txdr->desc); if (!txdr->desc) { setup_tx_desc_die: vfree(txdr->buffer_info); @@ -1804,6 +1814,7 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter, rxdr->size = rxdr->count * desc_len; rxdr->size = ALIGN(rxdr->size, 4096); + printk("we allocate %d descriptors for rx\n", rxdr->count); rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); if (!rxdr->desc) { @@ -3194,6 +3205,7 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) int tso; unsigned int f; + printk("try to send a packet\n"); /* This goes back to the question of how to logically map a tx queue * to a flow. Right now, performance is impacted slightly negatively * if using multiple tx queues. If the stack breaks away from a @@ -3671,6 +3683,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) struct e1000_hw *hw = &adapter->hw; u32 icr = er32(ICR); + printk("e1000_intr_msi is called\n"); /* in NAPI mode read ICR disables interrupts using IAM */ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { @@ -3717,6 +3730,7 @@ static irqreturn_t e1000_intr(int irq, void *data) if (unlikely((!icr) || test_bit(__E1000_RESETTING, &adapter->flags))) return IRQ_NONE; /* Not our interrupt */ + printk("e1000 gets an interrupt\n"); /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is * not set, then the adapter didn't send an interrupt */ if (unlikely(hw->mac_type >= e1000_82571 && @@ -3799,6 +3813,8 @@ static int e1000_clean(struct napi_struct *napi, int budget) e1000_irq_enable(adapter); } + printk("e1000_clean: budget: %d, work_done: %d, tx_cleaned: %d\n", + budget, work_done, tx_cleaned); return work_done; } @@ -3823,6 +3839,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, eop_desc = E1000_TX_DESC(*tx_ring, eop); while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { + printk("e1000_clean_tx_irq: check desc %d\n", eop); for (cleaned = false; !cleaned; ) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; @@ -4090,6 +4107,8 @@ next_desc: /* return some buffers to hardware, one at a time is too slow */ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { + printk("cleaned_count in the loop: %d\n", + cleaned_count); adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); cleaned_count = 0; } @@ -4129,6 +4148,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, unsigned int i; unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; + printk("e1000_alloc_rx_buffers is called\n"); i = rx_ring->next_to_use; buffer_info = &rx_ring->buffer_info[i]; @@ -4143,6 +4163,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, if (unlikely(!skb)) { /* Better luck next round */ adapter->alloc_rx_buff_failed++; + printk("check point 1\n"); break; } @@ -4156,6 +4177,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, /* Failed allocation, critical failure */ if (!skb) { dev_kfree_skb(oldskb); + printk("check point 2\n"); break; } @@ -4163,6 +4185,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, /* give up */ dev_kfree_skb(skb); dev_kfree_skb(oldskb); + printk("check point 3\n"); break; /* while !buffer_info->skb */ } @@ -4198,6 +4221,7 @@ map_skb: adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); + printk("check point 4\n"); break; /* while !buffer_info->skb */ } rx_desc = E1000_RX_DESC(*rx_ring, i); @@ -4208,7 +4232,10 @@ map_skb: buffer_info = &rx_ring->buffer_info[i]; } + printk("cleaned_count: %d\n", cleaned_count); if (likely(rx_ring->next_to_use != i)) { + printk("old rx_ring next_to_use: %d, new one: %d\n", + rx_ring->next_to_use, i); rx_ring->next_to_use = i; if (unlikely(i-- == 0)) i = (rx_ring->count - 1); @@ -4452,6 +4479,8 @@ static void e1000_vlan_rx_register(struct net_device *netdev, struct e1000_hw *hw = &adapter->hw; u32 ctrl, rctl; + printk ("********e1000_vlan_rx_register. grp: %p\n", grp); + if (!test_bit(__E1000_DOWN, &adapter->flags)) e1000_irq_disable(adapter); adapter->vlgrp = grp; diff --git a/libdde_linux26/lib/src/arch/l4/kmalloc.c b/libdde_linux26/lib/src/arch/l4/kmalloc.c index 0e94fb97..816f443c 100644 --- a/libdde_linux26/lib/src/arch/l4/kmalloc.c +++ b/libdde_linux26/lib/src/arch/l4/kmalloc.c @@ -131,14 +131,23 @@ void *__kmalloc(size_t size, gfp_t flags) struct kmem_cache *cache = find_cache(size); void **p; - if (cache) + if (cache) { /* allocate from cache */ p = kmem_cache_alloc(cache, flags); + if (!p) { + printk("__kmalloc: kmem_cache_alloc %s fails\n", + ((char **)cache)[0]); + } + } else { /* no cache for this size - use ddekit malloc */ p = ddekit_large_malloc(size); if (flags & __GFP_ZERO) memset (p, 0, size); + if (!p) { + printk("__kmalloc: ddekit_large_malloc %d fails\n", + size); + } } ddekit_log(DEBUG_MALLOC, "size=%d, cache=%p (%d) => %p", diff --git a/libdde_linux26/lib/src/arch/l4/res.c b/libdde_linux26/lib/src/arch/l4/res.c index fbd2d09b..a2ffb98f 100644 --- a/libdde_linux26/lib/src/arch/l4/res.c +++ b/libdde_linux26/lib/src/arch/l4/res.c @@ -99,8 +99,12 @@ struct resource * __request_region(struct resource *parent, switch (parent->flags) { case IORESOURCE_IO: + printk("IO: name: %s, start: %x, len: %d\n", + name, start, n); return l4dde26_request_region(start, n, name); case IORESOURCE_MEM: + printk("MEM: name: %s, start: %x, len: %d\n", + name, start, n); return l4dde26_request_mem_region(start, n, name); } @@ -161,7 +165,11 @@ void __iomem * ioremap(unsigned long phys_addr, unsigned long size) struct dde_mem_region *mreg = list_entry(pos, struct dde_mem_region, list); if (mreg->pa <= phys_addr && mreg->pa + mreg->size >= phys_addr + size) + { + printk ("ioremap: phys: %x <-> virt: %x\n", phys_addr, + (mreg->va + (phys_addr - mreg->pa))); return (void *)(mreg->va + (phys_addr - mreg->pa)); + } } return NULL; diff --git a/libdde_linux26/lib/src/net/core/skbuff.c b/libdde_linux26/lib/src/net/core/skbuff.c index 2f65e534..40d64a88 100644 --- a/libdde_linux26/lib/src/net/core/skbuff.c +++ b/libdde_linux26/lib/src/net/core/skbuff.c @@ -180,14 +180,19 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, /* Get the HEAD */ skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node); - if (!skb) + if (!skb) { + printk("kmem_cache_alloc_node fails\n"); goto out; + } size = SKB_DATA_ALIGN(size); data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info), gfp_mask, node); - if (!data) + if (!data) { + printk("kmalloc_node_track_caller %d fails\n", + size + sizeof(struct skb_shared_info)); goto nodata; + } /* * Only clear those fields we need to clear, not those that we will diff --git a/libmachdev/net.c b/libmachdev/net.c index 9a367a6b..ca6bca63 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -122,7 +122,7 @@ struct net_data *nd_head; extern struct device_emulation_ops linux_net_emulation_ops; -static int print_packet_size = 0; +static int print_packet_size = 1; mach_msg_type_t header_type = { @@ -299,7 +299,10 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, /* Search for the device. */ dev = search_netdev (name); if (!dev) - return D_NO_SUCH_DEVICE; + { + fprintf (stderr, "after search_netdev: cannot find %s\n", name); + return D_NO_SUCH_DEVICE; + } /* Allocate and initialize device data if this is the first open. */ nd = search_nd (dev); @@ -307,7 +310,10 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, { err = create_device_port (sizeof (*nd), &nd); if (err) - goto out; + { + fprintf (stderr, "after create_device_port: cannot create a port\n"); + goto out; + } nd->dev = dev; nd->device.emul_data = nd; @@ -333,7 +339,10 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, #endif if (dev_open(dev) < 0) - err = D_NO_SUCH_DEVICE; + { + fprintf (stderr, "after dev_open: cannot open the device\n"); + err = D_NO_SUCH_DEVICE; + } out: if (err) -- cgit v1.2.3 From 2fe1437bd35016309e9ac4cfe57fb3daca3ba0a0 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 31 May 2010 17:21:47 +0200 Subject: make glue code of networking more independant. This change is required for block device drivers. When block device drivers are linked to the glue code, the linker should be able to perform garbage collection and exclude the code of networking from the driver programs. --- dde_e100/Makefile | 2 +- dde_e100/main.c | 6 +++--- dde_e1000/Makefile | 2 +- dde_e1000/main.c | 6 +++--- dde_ne2k_pci/Makefile | 2 +- dde_ne2k_pci/main.c | 6 +++--- dde_pcnet32/Makefile | 2 +- dde_pcnet32/main.c | 6 +++--- dde_rtl8139/Makefile | 2 +- dde_rtl8139/main.c | 6 +++--- libmachdev/Makefile | 3 ++- libmachdev/device_emul.h | 2 +- libmachdev/ds_routines.c | 14 +++++++++----- libmachdev/machdev.h | 32 ++++++++++++++++++++++++++++++++ libmachdev/net.c | 25 +++++++++++++++---------- 15 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 libmachdev/machdev.h (limited to 'libmachdev/net.c') diff --git a/dde_e100/Makefile b/dde_e100/Makefile index fb1ed61e..27504068 100644 --- a/dde_e100/Makefile +++ b/dde_e100/Makefile @@ -10,7 +10,7 @@ TARGET = dde_e100 SRC_C = main.c e100.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_e100/main.c b/dde_e100/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_e100/main.c +++ b/dde_e100/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/dde_e1000/Makefile b/dde_e1000/Makefile index bfe7dbaf..ffdc17ab 100644 --- a/dde_e1000/Makefile +++ b/dde_e1000/Makefile @@ -10,7 +10,7 @@ TARGET = dde_e1000 SRC_C = main.c e1000_ethtool.c e1000_hw.c e1000_main.c e1000_param.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_e1000/main.c b/dde_e1000/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_e1000/main.c +++ b/dde_e1000/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/dde_ne2k_pci/Makefile b/dde_ne2k_pci/Makefile index 6cc27279..879904e1 100644 --- a/dde_ne2k_pci/Makefile +++ b/dde_ne2k_pci/Makefile @@ -10,7 +10,7 @@ TARGET = dde_ne2k_pci SRC_C = main.c ne2k-pci.c 8390.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_ne2k_pci/main.c b/dde_ne2k_pci/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_ne2k_pci/main.c +++ b/dde_ne2k_pci/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/dde_pcnet32/Makefile b/dde_pcnet32/Makefile index 89e67efd..ebbb271e 100644 --- a/dde_pcnet32/Makefile +++ b/dde_pcnet32/Makefile @@ -10,7 +10,7 @@ TARGET = dde_pcnet32 SRC_C = main.c pcnet32.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_pcnet32/main.c b/dde_pcnet32/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_pcnet32/main.c +++ b/dde_pcnet32/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/dde_rtl8139/Makefile b/dde_rtl8139/Makefile index dcc4a4f1..1af8e179 100644 --- a/dde_rtl8139/Makefile +++ b/dde_rtl8139/Makefile @@ -10,7 +10,7 @@ TARGET = dde_rtl8139 SRC_C = main.c 8139cp.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_rtl8139/main.c b/dde_rtl8139/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_rtl8139/main.c +++ b/dde_rtl8139/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/libmachdev/Makefile b/libmachdev/Makefile index daf13a82..f64e281a 100644 --- a/libmachdev/Makefile +++ b/libmachdev/Makefile @@ -22,7 +22,8 @@ libname = libmachdev SRCS = deviceUser.c machUser.c net.c ds_routines.c queue.c trivfs_server.c \ device_replyUser.c deviceServer.c notifyServer.c LCLHDRS = dev_hdr.h device_emul.h ds_routines.h vm_param.h \ - util.h queue.h io_req.h if_ether.h + util.h queue.h io_req.h if_ether.h machdev.h +installhdrs = machdev.h device_emul.h HURDLIBS = ports threads trivfs OBJS = $(SRCS:.c=.o) $(MIGSTUBS) diff --git a/libmachdev/device_emul.h b/libmachdev/device_emul.h index edcf6d07..a5bc4f77 100644 --- a/libmachdev/device_emul.h +++ b/libmachdev/device_emul.h @@ -31,7 +31,7 @@ /* Each emulation layer provides these operations. */ struct device_emulation_ops { - void (*init) (); + void (*init) (void); void (*reference) (void *); void (*dealloc) (void *); mach_port_t (*dev_to_port) (void *); diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index 1961a2f3..f6a8e76c 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -73,13 +73,12 @@ static struct port_class *dev_class; extern struct device_emulation_ops linux_net_emulation_ops; -#define NUM_EMULATION (sizeof (emulation_list) / sizeof (emulation_list[0])) +#define NUM_EMULATION num_emul +#define MAX_NUM_EMULATION 32 /* List of emulations. */ -static struct device_emulation_ops *emulation_list[] = -{ - &linux_net_emulation_ops, -}; +static struct device_emulation_ops *emulation_list[MAX_NUM_EMULATION]; +static int num_emul; boolean_t is_master_device (mach_port_t port); @@ -447,6 +446,11 @@ demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) return ret; } +void reg_dev_emul (struct device_emulation_ops *ops) +{ + emulation_list[num_emul++] = ops; +} + void ds_server() { /* Launch. */ diff --git a/libmachdev/machdev.h b/libmachdev/machdev.h new file mode 100644 index 00000000..27c488a5 --- /dev/null +++ b/libmachdev/machdev.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2010 Free Software Foundation, Inc. + Written by Zheng Da. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The GNU Hurd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This file declares interfaces used by driver programs. */ + +#ifndef __MACHDEV_H__ +#define __MACHDEV_H__ + +void ds_server(void); +void mach_device_init(void); +void register_net(void); +void trivfs_server(void); +int trivfs_init(void); + +#endif diff --git a/libmachdev/net.c b/libmachdev/net.c index ca6bca63..e785a5c8 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -102,7 +102,6 @@ struct skb_reply struct sk_buff; void skb_done_queue(struct sk_buff *skb); struct sk_buff *skb_done_dequeue(); -void linux_net_emulation_init (); void *skb_reply(struct sk_buff *skb); int netdev_flags(struct net_device *dev); char *netdev_addr(struct net_device *dev); @@ -116,7 +115,7 @@ int dev_open(struct net_device *dev); void *l4dde26_register_rx_callback(void *cb); void skb_done_head_init(); -struct net_data *nd_head; +static struct net_data *nd_head; /* Forward declarations. */ @@ -124,7 +123,7 @@ extern struct device_emulation_ops linux_net_emulation_ops; static int print_packet_size = 1; -mach_msg_type_t header_type = +static mach_msg_type_t header_type = { MACH_MSG_TYPE_BYTE, 8, @@ -135,7 +134,7 @@ mach_msg_type_t header_type = 0 }; -mach_msg_type_t packet_type = +static mach_msg_type_t packet_type = { MACH_MSG_TYPE_BYTE, /* name */ 8, /* size */ @@ -145,7 +144,7 @@ mach_msg_type_t packet_type = FALSE /* deallocate */ }; -struct net_data *search_nd (struct net_device *dev) +static struct net_data *search_nd (struct net_device *dev) { struct net_data *nd = nd_head; @@ -163,7 +162,7 @@ struct net_data *search_nd (struct net_device *dev) /* actions before freeing the sk_buff SKB. * If it returns 1, the packet will be deallocated later. */ -int +static int pre_kfree_skb (struct sk_buff *skb, void *data) { struct skb_reply *reply = data; @@ -190,7 +189,7 @@ pre_kfree_skb (struct sk_buff *skb, void *data) * Deliver the message to all right pfinet servers that * connects to the virtual network interface. */ -int +static int deliver_msg(mach_port_t dest, struct net_rcv_msg *msg) { mach_msg_return_t err; @@ -217,7 +216,7 @@ deliver_msg(mach_port_t dest, struct net_rcv_msg *msg) } /* Accept packet SKB received on an interface. */ -void +static void netif_rx_handle (char *data, int len, struct net_device *dev) { int pack_size; @@ -438,7 +437,7 @@ device_write (void *d, mach_port_t reply_port, /* * Other network operations */ -io_return_t +static io_return_t net_getstat(dev, flavor, status, count) struct net_device *dev; dev_flavor_t flavor; @@ -641,7 +640,7 @@ device_set_filter (void *d, mach_port_t port, int priority, } /* Do any initialization required for network devices. */ -void linux_net_emulation_init () +static void linux_net_emulation_init () { skb_done_head_init(); l4dde26_register_rx_callback(netif_rx_handle); @@ -667,3 +666,9 @@ struct device_emulation_ops linux_net_emulation_ops = NULL, NULL }; + +void register_net() +{ + extern void reg_dev_emul (struct device_emulation_ops *ops); + reg_dev_emul (&linux_net_emulation_ops); +} -- cgit v1.2.3 From 77042ddb052bbad8de75ffe7e46d5ec5b40c8c06 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 4 Jun 2010 07:34:32 +0200 Subject: convert linux errno to mach in libmachdev. --- libmachdev/Makefile | 7 +-- libmachdev/errno-base.h | 39 +++++++++++++++++ libmachdev/linux-errno.h | 109 +++++++++++++++++++++++++++++++++++++++++++++++ libmachdev/misc.c | 49 +++++++++++++++++++++ libmachdev/net.c | 6 +-- libmachdev/util.h | 2 + 6 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 libmachdev/errno-base.h create mode 100644 libmachdev/linux-errno.h create mode 100644 libmachdev/misc.c (limited to 'libmachdev/net.c') diff --git a/libmachdev/Makefile b/libmachdev/Makefile index f64e281a..2bd294ad 100644 --- a/libmachdev/Makefile +++ b/libmachdev/Makefile @@ -20,13 +20,14 @@ makemode := library libname = libmachdev SRCS = deviceUser.c machUser.c net.c ds_routines.c queue.c trivfs_server.c \ - device_replyUser.c deviceServer.c notifyServer.c + device_replyUser.c deviceServer.c notifyServer.c misc.c LCLHDRS = dev_hdr.h device_emul.h ds_routines.h vm_param.h \ - util.h queue.h io_req.h if_ether.h machdev.h + util.h queue.h io_req.h if_ether.h machdev.h linux-errno.h \ + errno-base.h installhdrs = machdev.h device_emul.h HURDLIBS = ports threads trivfs OBJS = $(SRCS:.c=.o) $(MIGSTUBS) include ../Makeconf -CFLAGS += +CFLAGS += -I../libddekit/include diff --git a/libmachdev/errno-base.h b/libmachdev/errno-base.h new file mode 100644 index 00000000..65115978 --- /dev/null +++ b/libmachdev/errno-base.h @@ -0,0 +1,39 @@ +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif diff --git a/libmachdev/linux-errno.h b/libmachdev/linux-errno.h new file mode 100644 index 00000000..e8852c09 --- /dev/null +++ b/libmachdev/linux-errno.h @@ -0,0 +1,109 @@ +#ifndef _ASM_GENERIC_ERRNO_H +#define _ASM_GENERIC_ERRNO_H + +#include + +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#endif diff --git a/libmachdev/misc.c b/libmachdev/misc.c new file mode 100644 index 00000000..d5df3663 --- /dev/null +++ b/libmachdev/misc.c @@ -0,0 +1,49 @@ +#include + +#include + +#include "linux-errno.h" + +int +linux_to_mach_error (int err); +{ + switch (err) + { + case 0: + return D_SUCCESS; + + case -EPERM: + return D_INVALID_OPERATION; + + case -EIO: + return D_IO_ERROR; + + case -ENXIO: + return D_NO_SUCH_DEVICE; + + case -EACCES: + return D_INVALID_OPERATION; + + case -EFAULT: + return D_INVALID_SIZE; + + case -EBUSY: + return D_ALREADY_OPEN; + + case -EINVAL: + return D_INVALID_SIZE; + + case -EROFS: + return D_READ_ONLY; + + case -EWOULDBLOCK: + return D_WOULD_BLOCK; + + case -ENOMEM: + return D_NO_MEMORY; + + default: + ddekit_printf ("linux_to_mach_error: unknown code %d\n", err); + return D_IO_ERROR; + } +} diff --git a/libmachdev/net.c b/libmachdev/net.c index e785a5c8..b21d6333 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -337,10 +337,10 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, if_init_queues (ifp); #endif - if (dev_open(dev) < 0) + if (err = dev_open(dev) < 0) { fprintf (stderr, "after dev_open: cannot open the device\n"); - err = D_NO_SUCH_DEVICE; + err = linux_to_mach_error (err); } out: @@ -396,7 +396,7 @@ device_write (void *d, mach_port_t reply_port, err = linux_pkg_xmit (data, count, skb_reply, pre_kfree_skb, dev); vm_deallocate (mach_task_self (), (vm_address_t) data, count); if (err) - return err; + return linux_to_mach_error (err); /* Send packet to filters. */ // TODO should I deliver the packet to other network stacks? diff --git a/libmachdev/util.h b/libmachdev/util.h index 6fb1db28..1c62b0d6 100644 --- a/libmachdev/util.h +++ b/libmachdev/util.h @@ -30,4 +30,6 @@ #endif +int linux_to_mach_error (int err); + #endif -- cgit v1.2.3 From 21bf6f025d94c2987dfe30a0b327b6dfab7a8bff Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 4 Jun 2010 16:51:24 +0200 Subject: support block devices in the DDE library. --- libdde_linux26/lib/src/Makefile | 3 +- libdde_linux26/lib/src/arch/l4/mach_glue.c | 87 ---------- libdde_linux26/lib/src/mach_glue/block.c | 77 +++++++++ libdde_linux26/lib/src/mach_glue/net.c | 87 ++++++++++ libmachdev/Makefile | 2 +- libmachdev/block.c | 250 +++++++++++++++++++++++++++++ libmachdev/mach_glue.h | 30 ++++ libmachdev/machdev.h | 1 + libmachdev/net.c | 19 +-- windhoek/Makefile | 4 +- windhoek/main.c | 1 + 11 files changed, 453 insertions(+), 108 deletions(-) delete mode 100644 libdde_linux26/lib/src/arch/l4/mach_glue.c create mode 100644 libdde_linux26/lib/src/mach_glue/block.c create mode 100644 libdde_linux26/lib/src/mach_glue/net.c create mode 100644 libmachdev/block.c create mode 100644 libmachdev/mach_glue.h (limited to 'libmachdev/net.c') diff --git a/libdde_linux26/lib/src/Makefile b/libdde_linux26/lib/src/Makefile index 3743f91b..947f11b9 100644 --- a/libdde_linux26/lib/src/Makefile +++ b/libdde_linux26/lib/src/Makefile @@ -150,7 +150,7 @@ SRC_C_libdde_linux26.o.a += \ ################################################################## SRC_C_libdde_linux26_net.a += \ arch/l4/net.c \ - arch/l4/mach_glue.c \ + mach_glue/net.c \ drivers/net/mii.c \ net/core/dev.c \ net/core/dev_mcast.c \ @@ -180,6 +180,7 @@ SRC_C_libdde_linux26_sound.a += \ # SRC_C_libdde_linux26_block.a += \ arch/l4/inodes.c \ + mach_glue/block.c \ block/blk-barrier.c \ block/blk-core.c \ block/blk-exec.c \ diff --git a/libdde_linux26/lib/src/arch/l4/mach_glue.c b/libdde_linux26/lib/src/arch/l4/mach_glue.c deleted file mode 100644 index 48373a90..00000000 --- a/libdde_linux26/lib/src/arch/l4/mach_glue.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include - -/* List of sk_buffs waiting to be freed. */ -static struct sk_buff_head skb_done_list; - -struct net_device *search_netdev (char *name) -{ - struct net_device *dev; - struct net_device *found = NULL; - struct net *net; - - printk("search device %s\n", name); - read_lock(&dev_base_lock); - for_each_net(net) { - for_each_netdev(net, dev) { - printk("there is device %s, base addr: %x\n", - dev->name, dev->base_addr); - if (!strcmp (name, dev->name)) - { - found = dev; - goto end; - } - } - } -end: - read_unlock(&dev_base_lock); - return found; -} - -int linux_pkg_xmit (char *pkg_data, int len, void *del_data, - int (*del_func) (struct sk_buff *, void *), - struct net_device *dev) -{ - struct sk_buff *skb; - - if (len == 0 || len > dev->mtu + dev->hard_header_len) - return EINVAL; - - /* Allocate a sk_buff. */ - skb = dev_alloc_skb (len); - if (!skb) - return ENOMEM; - - skb->del_data = del_data; - skb->pre_del_func = del_func; - - /* Copy user data. This is only required if it spans multiple pages. */ - skb->len = len; - skb->tail = skb->data + len; - - memcpy (skb->data, pkg_data, len); - - skb->dev = dev; - - return dev_queue_xmit(skb); -} - -char *netdev_addr(struct net_device *dev) -{ - return dev->dev_addr; -} - -int netdev_flags(struct net_device *dev) -{ - return dev->flags; -} - -void *skb_reply(struct sk_buff *skb) -{ - return skb->del_data; -} - -void skb_done_head_init() -{ - skb_queue_head_init (&skb_done_list); -} - -struct sk_buff *skb_done_dequeue() -{ - return skb_dequeue (&skb_done_list); -} - -void skb_done_queue(struct sk_buff *skb) -{ - skb_queue_tail (&skb_done_list, skb); -} diff --git a/libdde_linux26/lib/src/mach_glue/block.c b/libdde_linux26/lib/src/mach_glue/block.c new file mode 100644 index 00000000..7eac7e46 --- /dev/null +++ b/libdde_linux26/lib/src/mach_glue/block.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include + +struct gendisk *find_disk_by_name (char *); +void dde_page_cache_add (struct page *); + +struct block_device *open_block_dev (char *name, int part, fmode_t mode) +{ + struct gendisk *disk = find_disk_by_name (name); + dev_t devid = MKDEV (disk->major, disk->first_minor + part); + return open_by_devnum (devid, mode); +} + +/* write a piece of data to a block device. + * DATA must be in one page. + * SECTORNR: the writing location in sectors. */ +int block_dev_write (struct block_device *dev, int sectornr, + char *data, int count, void (*write_done (int err))) +{ + int err = 0; + struct bio *bio; + struct page *page; + int i; + + void end_bio (struct bio *bio, int err) + { + write_done (err); + } + + assert (count <= PAGE_SIZE); + bio = bio_alloc (GFP_NOIO, 1); + if (bio == NULL) + { + err = ENOMEM; + goto out; + } + + page = kmalloc (sizeof (*page), GFP_KERNEL); + if (page == NULL) + { + err = ENOMEM; + goto out; + } + + bio->bi_sector = sectornr; + bio->bi_bdev = dev; + page->virtual = data; + dde_page_cache_add (page); + bio->bi_io_vec[0].bv_page = page; + bio->bi_io_vec[0].bv_len = count; + bio->bi_io_vec[0].bv_offset = (int) data & ~PAGE_MASK; + + bio->bi_vcnt = 1; + bio->bi_idx = 0; + bio->bi_size = count; + + bio->bi_end_io = end_bio; + bio->bi_private = NULL; + bio_get (bio); + submit_bio (WRITE, bio); + if (bio_flagged (bio, BIO_EOPNOTSUPP)) + { + err = -EOPNOTSUPP; + goto out; + } + bio_put (bio); +out: + if (err) + { + if (bio) + bio_put (bio); + kfree (page); + } + return err; +} diff --git a/libdde_linux26/lib/src/mach_glue/net.c b/libdde_linux26/lib/src/mach_glue/net.c new file mode 100644 index 00000000..48373a90 --- /dev/null +++ b/libdde_linux26/lib/src/mach_glue/net.c @@ -0,0 +1,87 @@ +#include +#include + +/* List of sk_buffs waiting to be freed. */ +static struct sk_buff_head skb_done_list; + +struct net_device *search_netdev (char *name) +{ + struct net_device *dev; + struct net_device *found = NULL; + struct net *net; + + printk("search device %s\n", name); + read_lock(&dev_base_lock); + for_each_net(net) { + for_each_netdev(net, dev) { + printk("there is device %s, base addr: %x\n", + dev->name, dev->base_addr); + if (!strcmp (name, dev->name)) + { + found = dev; + goto end; + } + } + } +end: + read_unlock(&dev_base_lock); + return found; +} + +int linux_pkg_xmit (char *pkg_data, int len, void *del_data, + int (*del_func) (struct sk_buff *, void *), + struct net_device *dev) +{ + struct sk_buff *skb; + + if (len == 0 || len > dev->mtu + dev->hard_header_len) + return EINVAL; + + /* Allocate a sk_buff. */ + skb = dev_alloc_skb (len); + if (!skb) + return ENOMEM; + + skb->del_data = del_data; + skb->pre_del_func = del_func; + + /* Copy user data. This is only required if it spans multiple pages. */ + skb->len = len; + skb->tail = skb->data + len; + + memcpy (skb->data, pkg_data, len); + + skb->dev = dev; + + return dev_queue_xmit(skb); +} + +char *netdev_addr(struct net_device *dev) +{ + return dev->dev_addr; +} + +int netdev_flags(struct net_device *dev) +{ + return dev->flags; +} + +void *skb_reply(struct sk_buff *skb) +{ + return skb->del_data; +} + +void skb_done_head_init() +{ + skb_queue_head_init (&skb_done_list); +} + +struct sk_buff *skb_done_dequeue() +{ + return skb_dequeue (&skb_done_list); +} + +void skb_done_queue(struct sk_buff *skb) +{ + skb_queue_tail (&skb_done_list, skb); +} diff --git a/libmachdev/Makefile b/libmachdev/Makefile index 2bd294ad..7475d041 100644 --- a/libmachdev/Makefile +++ b/libmachdev/Makefile @@ -20,7 +20,7 @@ makemode := library libname = libmachdev SRCS = deviceUser.c machUser.c net.c ds_routines.c queue.c trivfs_server.c \ - device_replyUser.c deviceServer.c notifyServer.c misc.c + device_replyUser.c deviceServer.c notifyServer.c misc.c block.c LCLHDRS = dev_hdr.h device_emul.h ds_routines.h vm_param.h \ util.h queue.h io_req.h if_ether.h machdev.h linux-errno.h \ errno-base.h diff --git a/libmachdev/block.c b/libmachdev/block.c new file mode 100644 index 00000000..54048fde --- /dev/null +++ b/libmachdev/block.c @@ -0,0 +1,250 @@ +/* + * Linux block driver support. + * + * Copyright (C) 1996 The University of Utah and the Computer Systems + * Laboratory at the University of Utah (CSL) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Shantanu Goel, University of Utah CSL + */ + +#include +#include +#include + +#include "mach_U.h" + +#include +#include + +#define MACH_INCLUDE + +#include + +#include "vm_param.h" +#include "device_reply_U.h" +#include "dev_hdr.h" +#include "util.h" +#include "mach_glue.h" + +/* One of these is associated with each open instance of a device. */ +struct block_data +{ + struct port_info port; /* device port */ + struct emul_device device; /* generic device structure */ + dev_mode_t mode; + struct block_device *dev; +}; + +/* Return a send right associated with network device ND. */ +static mach_port_t +dev_to_port (void *nd) +{ + return (nd + ? ports_get_send_right (nd) + : MACH_PORT_NULL); +} + +extern struct device_emulation_ops linux_block_emulation_ops; + +#define DISK_NAME_LEN 32 + +/* Parse the device NAME. + Set *SLICE to be the DOS partition and + *PART the BSD/Mach partition, if any. */ +static char * +translate_name (char *name, int *slice, int *part) +{ + char *p, *q, *end; + char *ret; + int disk_num; + + /* Parse name into name, unit, DOS partition (slice) and partition. */ + for (*slice = 0, *part = -1, p = name; isalpha (*p); p++) + ; + if (p == name || ! isdigit (*p)) + return NULL; + end = p; + disk_num = strtol (p, &p, 0); + if (disk_num < 0 || disk_num > 26) + return NULL; +// do +// p++; +// while (isdigit (*p)); + if (*p) + { + q = p; + if (*q == 's' && isdigit (*(q + 1))) + { + q++; + do + *slice = *slice * 10 + *q++ - '0'; + while (isdigit (*q)); + if (! *q) + goto find_major; + } + if (! isalpha (*q) || *(q + 1)) + return NULL; + *part = *q - 'a'; + } + +find_major: + ret = malloc (DISK_NAME_LEN); + sprintf (ret, "hd%c", 'a' + disk_num); + return ret; +} + +static io_return_t +device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, + dev_mode_t mode, char *name, device_t *devp) +{ + io_return_t err = D_SUCCESS; + struct block_data *bd = NULL; + int slice, part; + char *dev_name = NULL; + + dev_name = translate_name (name, &slice, &part); + + // TODO when the port isn't used by clients, it should be destroyed. + err = create_device_port (sizeof (*bd), &bd); + if (err) + { + ddekit_printf ("after create_device_port: cannot create a port\n"); + goto out; + } + bd->dev = open_block_dev (dev_name, slice, mode); + if (bd->dev < 0) + { + ddekit_printf ("open_block_dev fails with %d\n", bd->dev); + err = linux_to_mach_error (err); + goto out; + } + bd->device.emul_data = bd; + bd->device.emul_ops = &linux_block_emulation_ops; + bd->mode = mode; + +out: + free (dev_name); + if (err) + { + if (bd) + { + ports_destroy_right (bd); + bd = NULL; + } + } + else + *devp = ports_get_right (bd); + return err; +} + +static io_return_t +device_write (void *d, mach_port_t reply_port, + mach_msg_type_name_t reply_port_type, dev_mode_t mode, + recnum_t bn, io_buf_ptr_t data, unsigned int count, + int *bytes_written) +{ + struct block_data *bd = d; + /* the number of pages that contain DATA. */ + int npages = (((int) data + count) - ((int) data & ~PAGE_MASK) + + PAGE_MASK) / PAGE_SIZE; + io_return_t err = D_SUCCESS; + int i; + int writes = 0; + + void write_done (int err) + { + int len = err ? 0 : count; + writes--; + if (writes == 0) + { + err = linux_to_mach_error (err); + ds_device_write_reply (reply_port, reply_port_type, err, len); + } + } + + /* the data is at the beginning of a page. */ + if ((int) data & ~PAGE_MASK) + return D_INVALID_OPERATION; + + if ((bd->mode & D_WRITE) == 0) + return D_INVALID_OPERATION; + + for (i = 0; i < npages; i++) + { + int size = PAGE_SIZE - ((int) data &~PAGE_MASK) > count ? + PAGE_SIZE - ((int) data &~PAGE_MASK) : count; + + err = block_dev_write (bd->dev, bn, data, count, write_done); + if (err) + break; + bn += count >> 9; + data += size; + count -= size; + writes++; + } + if (writes) + return MIG_NO_REPLY; + return linux_to_mach_error (err); +} + +static io_return_t +device_read (void *d, mach_port_t reply_port, + mach_msg_type_name_t reply_port_type, dev_mode_t mode, + recnum_t bn, int count, io_buf_ptr_t *data, + unsigned *bytes_read) +{ + struct block_data *bd = d; + + if ((bd->mode & D_READ) == 0) + return D_INVALID_OPERATION; + *bytes_read = 0; + return D_SUCCESS; +} + +static io_return_t +device_get_status (void *d, dev_flavor_t flavor, dev_status_t status, + mach_msg_type_number_t *count) +{ + struct block_data *bd = (struct block_data *) d; + return D_SUCCESS; +} + +struct device_emulation_ops linux_block_emulation_ops = +{ + NULL, + NULL, + dev_to_port, + device_open, + NULL, + device_write, + NULL, + device_read, + NULL, + NULL, + device_get_status, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +void register_block() +{ + extern void reg_dev_emul (struct device_emulation_ops *ops); + reg_dev_emul (&linux_block_emulation_ops); +} diff --git a/libmachdev/mach_glue.h b/libmachdev/mach_glue.h new file mode 100644 index 00000000..6d0870ed --- /dev/null +++ b/libmachdev/mach_glue.h @@ -0,0 +1,30 @@ +#ifndef __MACH_GLUE_H__ +#define __MACH_GLUE_H__ + +/* network */ +#include + +struct sk_buff; +struct net_device; +void skb_done_queue(struct sk_buff *skb); +struct sk_buff *skb_done_dequeue(); +void *skb_reply(struct sk_buff *skb); +int netdev_flags(struct net_device *dev); +char *netdev_addr(struct net_device *dev); +int dev_change_flags (struct net_device *dev, short flags); +int linux_pkg_xmit (char *pkg_data, int len, void *del_data, + int (*del_func) (struct sk_buff *, void *), + struct net_device *dev); +struct net_device *search_netdev (char *name); +void kfree_skb (struct sk_buff *skb); +int dev_open(struct net_device *dev); +void *l4dde26_register_rx_callback(void *cb); +void skb_done_head_init(); + +/* block device */ +struct block_device; +struct block_device *open_block_dev (char *name, int part, dev_mode_t mode); +int block_dev_write (struct block_device *dev, int sectornr, + char *data, int count, void (*write_done) (int err)); + +#endif diff --git a/libmachdev/machdev.h b/libmachdev/machdev.h index 27c488a5..cfa4b2d4 100644 --- a/libmachdev/machdev.h +++ b/libmachdev/machdev.h @@ -26,6 +26,7 @@ void ds_server(void); void mach_device_init(void); void register_net(void); +void register_block(void); void trivfs_server(void); int trivfs_init(void); diff --git a/libmachdev/net.c b/libmachdev/net.c index b21d6333..8c435b4b 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -74,6 +74,7 @@ #include "dev_hdr.h" #include "if_ether.h" #include "util.h" +#include "mach_glue.h" #define ether_header ethhdr @@ -99,22 +100,6 @@ struct skb_reply int pkglen; }; -struct sk_buff; -void skb_done_queue(struct sk_buff *skb); -struct sk_buff *skb_done_dequeue(); -void *skb_reply(struct sk_buff *skb); -int netdev_flags(struct net_device *dev); -char *netdev_addr(struct net_device *dev); -int dev_change_flags (struct net_device *dev, short flags); -int linux_pkg_xmit (char *pkg_data, int len, void *del_data, - int (*del_func) (struct sk_buff *, void *), - struct net_device *dev); -struct net_device *search_netdev (char *name); -void kfree_skb (struct sk_buff *skb); -int dev_open(struct net_device *dev); -void *l4dde26_register_rx_callback(void *cb); -void skb_done_head_init(); - static struct net_data *nd_head; /* Forward declarations. */ @@ -337,7 +322,7 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, if_init_queues (ifp); #endif - if (err = dev_open(dev) < 0) + if ((err = dev_open(dev)) < 0) { fprintf (stderr, "after dev_open: cannot open the device\n"); err = linux_to_mach_error (err); diff --git a/windhoek/Makefile b/windhoek/Makefile index 6f355bb9..803e8dba 100644 --- a/windhoek/Makefile +++ b/windhoek/Makefile @@ -27,8 +27,8 @@ SRC_C += $(IDEFILES) \ $(CDROMFILES) \ $(PARTITIONFILES) -LIBS += --whole-archive -ldde_linux26_block --no-whole-archive \ - -ldde_linux26.o -lddekit ../libmachdev/libmachdev.a \ +LIBS += --whole-archive --no-whole-archive ../libmachdev/libmachdev.a \ + -ldde_linux26_block -ldde_linux26.o -lddekit \ -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc \ -lports -lhurd-slab diff --git a/windhoek/main.c b/windhoek/main.c index 6c3cdb89..c4e88666 100644 --- a/windhoek/main.c +++ b/windhoek/main.c @@ -66,6 +66,7 @@ int main(int argc, const char **argv) printk("| ready to rumble.... |\n"); printk("+----------------------------------------+\n"); + register_block (); mach_device_init(); trivfs_init(); -- cgit v1.2.3 From 823e9dd9c55a1f34259c5398497439f5663ff2a4 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 21 Jun 2010 09:59:01 +0200 Subject: fix port leak in block glue code of libmachdev. --- libmachdev/Makefile | 5 ++++- libmachdev/block.c | 9 +++++++-- libmachdev/device_emul.h | 3 ++- libmachdev/ds_routines.c | 4 ++-- libmachdev/net.c | 4 +++- 5 files changed, 18 insertions(+), 7 deletions(-) (limited to 'libmachdev/net.c') diff --git a/libmachdev/Makefile b/libmachdev/Makefile index e65a453a..22909949 100644 --- a/libmachdev/Makefile +++ b/libmachdev/Makefile @@ -20,7 +20,7 @@ makemode := library libname = libmachdev SRCS = deviceUser.c machUser.c net.c ds_routines.c queue.c trivfs_server.c \ - device_replyUser.c deviceServer.c notifyServer.c misc.c block.c + device_replyUser.c ourdeviceServer.c notifyServer.c misc.c block.c LCLHDRS = dev_hdr.h device_emul.h ds_routines.h vm_param.h \ util.h queue.h io_req.h if_ether.h machdev.h linux-errno.h \ errno-base.h @@ -31,3 +31,6 @@ OBJS = $(SRCS:.c=.o) $(MIGSTUBS) include ../Makeconf CFLAGS += -I$(top_srcdir)/libddekit/include + +ourdevice.defs: device.defs + $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@ diff --git a/libmachdev/block.c b/libmachdev/block.c index 5400f60b..4aa07672 100644 --- a/libmachdev/block.c +++ b/libmachdev/block.c @@ -109,7 +109,8 @@ find_major: static io_return_t device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, - dev_mode_t mode, char *name, device_t *devp) + dev_mode_t mode, char *name, device_t *devp, + mach_msg_type_name_t *devicePoly) { io_return_t err = D_SUCCESS; struct block_data *bd = NULL; @@ -149,7 +150,11 @@ out: } } else - *devp = ports_get_send_right (bd); + { + *devp = ports_get_send_right (bd); + ports_port_deref (bd); + *devicePoly = MACH_MSG_TYPE_MOVE_SEND; + } return err; } diff --git a/libmachdev/device_emul.h b/libmachdev/device_emul.h index a5bc4f77..e27799cb 100644 --- a/libmachdev/device_emul.h +++ b/libmachdev/device_emul.h @@ -36,7 +36,8 @@ struct device_emulation_ops void (*dealloc) (void *); mach_port_t (*dev_to_port) (void *); io_return_t (*open) (mach_port_t, mach_msg_type_name_t, - dev_mode_t, char *, device_t *); + dev_mode_t, char *, device_t *, + mach_msg_type_name_t *type); io_return_t (*close) (void *); io_return_t (*write) (void *, mach_port_t, mach_msg_type_name_t, dev_mode_t, recnum_t, io_buf_ptr_t, unsigned, int *); diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index df9146a0..71457e03 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -161,7 +161,7 @@ ds_device_irq_enable (mach_port_t master_port, io_return_t ds_device_open (mach_port_t open_port, mach_port_t reply_port, mach_msg_type_name_t reply_port_type, dev_mode_t mode, - char *name, device_t *devp) + char *name, device_t *devp, mach_msg_type_name_t *devicePoly) { int i; io_return_t err; @@ -181,7 +181,7 @@ ds_device_open (mach_port_t open_port, mach_port_t reply_port, for (i = 0; i < NUM_EMULATION; i++) { err = (*emulation_list[i]->open) (reply_port, reply_port_type, - mode, name, devp); + mode, name, devp, devicePoly); if (err != D_NO_SUCH_DEVICE) break; } diff --git a/libmachdev/net.c b/libmachdev/net.c index 8c435b4b..b9d76731 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -273,7 +273,8 @@ void if_init_queues(ifp) static io_return_t device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, - dev_mode_t mode, char *name, device_t *devp) + dev_mode_t mode, char *name, device_t *devp, + mach_msg_type_name_t *devicePoly) { io_return_t err = D_SUCCESS; struct net_device *dev; @@ -357,6 +358,7 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, } *devp = ports_get_right (nd); + *devicePoly = MACH_MSG_TYPE_COPY_SEND; return D_SUCCESS; } -- cgit v1.2.3 From 5a9d844a537293b0398f22003cd31bb61864f746 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sun, 1 Aug 2010 15:57:31 +0200 Subject: Use BPF to filter the packets to be delivered. --- libdde_linux26/lib/src/mach_glue/net.c | 25 +++++ libmachdev/Makefile | 2 +- libmachdev/if_hdr.h | 165 +++++++++++++++++++++++++++++++++ libmachdev/mach_glue.h | 7 ++ libmachdev/net.c | 118 +++++++++++++---------- 5 files changed, 265 insertions(+), 52 deletions(-) create mode 100644 libmachdev/if_hdr.h (limited to 'libmachdev/net.c') diff --git a/libdde_linux26/lib/src/mach_glue/net.c b/libdde_linux26/lib/src/mach_glue/net.c index 48373a90..3ab9e44f 100644 --- a/libdde_linux26/lib/src/mach_glue/net.c +++ b/libdde_linux26/lib/src/mach_glue/net.c @@ -66,6 +66,31 @@ int netdev_flags(struct net_device *dev) return dev->flags; } +char *netdev_name (struct net_device *dev) +{ + return dev->name; +} + +unsigned int netdev_mtu (struct net_device *dev) +{ + return dev->mtu; +} + +unsigned short netdev_header_len (struct net_device *dev) +{ + return dev->hard_header_len; +} + +unsigned short netdev_type (struct net_device *dev) +{ + return dev->type; +} + +unsigned char netdev_addr_len (struct net_device *dev) +{ + return dev->addr_len; +} + void *skb_reply(struct sk_buff *skb) { return skb->del_data; diff --git a/libmachdev/Makefile b/libmachdev/Makefile index 22909949..224dfddb 100644 --- a/libmachdev/Makefile +++ b/libmachdev/Makefile @@ -30,7 +30,7 @@ OBJS = $(SRCS:.c=.o) $(MIGSTUBS) include ../Makeconf -CFLAGS += -I$(top_srcdir)/libddekit/include +CFLAGS += -I$(top_srcdir)/libddekit/include -I$(top_srcdir)/libbpf ourdevice.defs: device.defs $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@ diff --git a/libmachdev/if_hdr.h b/libmachdev/if_hdr.h new file mode 100644 index 00000000..74d0fa8a --- /dev/null +++ b/libmachdev/if_hdr.h @@ -0,0 +1,165 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Taken from (bsd)net/if.h. Modified for MACH kernel. + */ +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. The name of the Laboratory may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if.h 7.3 (Berkeley) 6/27/88 + */ + +#ifndef _IF_HDR_ +#define _IF_HDR_ + +#include +#include +#include + +#if 0 +/* + * Queue for network output and filter input. + */ +struct ifqueue { + queue_head_t ifq_head; /* queue of io_req_t */ + int ifq_len; /* length of queue */ + int ifq_maxlen; /* maximum length of queue */ + int ifq_drops; /* number of packets dropped + because queue full */ + decl_simple_lock_data(, + ifq_lock) /* lock for queue and counters */ +}; +#endif + +/* + * Header for network interface drivers. + */ +struct ifnet { + short if_unit; /* unit number */ + short if_flags; /* up/down, broadcast, etc. */ + short if_timer; /* time until if_watchdog called */ + short if_mtu; /* maximum transmission unit */ + short if_header_size; /* length of header */ + short if_header_format; /* format of hardware header */ + short if_address_size; /* length of hardware address */ + short if_alloc_size; /* size of read buffer to allocate */ + char *if_address; /* pointer to hardware address */ +// struct ifqueue if_snd; /* output queue */ + if_filter_list_t port_list; + struct mutex if_rcv_port_list_lock;/* lock for input filter list */ + struct mutex if_snd_port_list_lock;/* lock for output filter list */ +/* statistics */ + int if_ipackets; /* packets received */ + int if_ierrors; /* input errors */ + int if_opackets; /* packets sent */ + int if_oerrors; /* output errors */ + int if_collisions; /* collisions on csma interfaces */ + int if_rcvdrops; /* packets received but dropped */ +}; + +#define IFF_UP 0x0001 /* interface is up */ +#define IFF_BROADCAST 0x0002 /* interface can broadcast */ +#define IFF_DEBUG 0x0004 /* turn on debugging */ +#define IFF_LOOPBACK 0x0008 /* is a loopback net */ +#define IFF_POINTOPOINT 0x0010 /* point-to-point link */ +#define IFF_RUNNING 0x0040 /* resources allocated */ +#define IFF_NOARP 0x0080 /* no address resolution protocol */ +#define IFF_PROMISC 0x0100 /* receive all packets */ +#define IFF_ALLMULTI 0x0200 /* receive all multicast packets */ +#define IFF_BRIDGE 0x0100 /* support token ring routing field */ +#define IFF_SNAP 0x0200 /* support extended sap header */ + +/* internal flags only: */ +#define IFF_CANTCHANGE (IFF_BROADCAST | IFF_POINTOPOINT | IFF_RUNNING) + +/* + * Output queues (ifp->if_snd) + * have queues of messages stored on ifqueue structures. Entries + * are added to and deleted from these structures by these macros, which + * should be called with ipl raised to splimp(). + * XXX locking XXX + */ + +#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) +#define IF_DROP(ifq) ((ifq)->ifq_drops++) +#define IF_ENQUEUE(ifq, ior) { \ + simple_lock(&(ifq)->ifq_lock); \ + enqueue_tail(&(ifq)->ifq_head, (queue_entry_t)ior); \ + (ifq)->ifq_len++; \ + simple_unlock(&(ifq)->ifq_lock); \ +} +#define IF_PREPEND(ifq, ior) { \ + simple_lock(&(ifq)->ifq_lock); \ + enqueue_head(&(ifq)->ifq_head, (queue_entry_t)ior); \ + (ifq)->ifq_len++; \ + simple_unlock(&(ifq)->ifq_lock); \ +} + +#define IF_DEQUEUE(ifq, ior) { \ + simple_lock(&(ifq)->ifq_lock); \ + if (((ior) = (io_req_t)dequeue_head(&(ifq)->ifq_head)) != 0) \ + (ifq)->ifq_len--; \ + simple_unlock(&(ifq)->ifq_lock); \ +} + +#define IFQ_MAXLEN 50 + +#define IFQ_INIT(ifq) { \ + queue_init(&(ifq)->ifq_head); \ + simple_lock_init(&(ifq)->ifq_lock); \ + (ifq)->ifq_len = 0; \ + (ifq)->ifq_maxlen = IFQ_MAXLEN; \ + (ifq)->ifq_drops = 0; \ +} + +#define IFNET_SLOWHZ 1 /* granularity is 1 second */ + +#endif /* _IF_HDR_ */ diff --git a/libmachdev/mach_glue.h b/libmachdev/mach_glue.h index 6d0870ed..d1bd1fc7 100644 --- a/libmachdev/mach_glue.h +++ b/libmachdev/mach_glue.h @@ -9,8 +9,15 @@ struct net_device; void skb_done_queue(struct sk_buff *skb); struct sk_buff *skb_done_dequeue(); void *skb_reply(struct sk_buff *skb); + int netdev_flags(struct net_device *dev); char *netdev_addr(struct net_device *dev); +char *netdev_name (struct net_device *dev); +unsigned int netdev_mtu (struct net_device *dev); +unsigned short netdev_header_len (struct net_device *dev); +unsigned short netdev_type (struct net_device *dev); +unsigned char netdev_addr_len (struct net_device *dev); + int dev_change_flags (struct net_device *dev, short flags); int linux_pkg_xmit (char *pkg_data, int len, void *del_data, int (*del_func) (struct sk_buff *, void *), diff --git a/libmachdev/net.c b/libmachdev/net.c index b9d76731..88b1d6c8 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -61,6 +61,7 @@ #include #include #include +#include #include "mach_U.h" @@ -75,6 +76,7 @@ #include "if_ether.h" #include "util.h" #include "mach_glue.h" +#include "if_hdr.h" #define ether_header ethhdr @@ -86,9 +88,8 @@ extern struct port_class *dev_class; struct net_data { struct port_info port; /* device port */ -// struct ifnet ifnet; /* Mach ifnet structure (needed for filters) */ struct emul_device device; /* generic device structure */ - mach_port_t delivery_port; + struct ifnet ifnet; /* Mach ifnet structure (needed for filters) */ struct net_device *dev; /* Linux network device structure */ struct net_data *next; }; @@ -174,10 +175,12 @@ pre_kfree_skb (struct sk_buff *skb, void *data) * Deliver the message to all right pfinet servers that * connects to the virtual network interface. */ -static int -deliver_msg(mach_port_t dest, struct net_rcv_msg *msg) +int +deliver_msg(struct net_rcv_msg *msg, if_filter_list_t *ifp) { mach_msg_return_t err; + queue_head_t *if_port_list; + net_rcv_port_t infp, nextfp; msg->msg_hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); /* remember message sizes must be rounded up */ @@ -185,19 +188,42 @@ deliver_msg(mach_port_t dest, struct net_rcv_msg *msg) msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL; msg->msg_hdr.msgh_id = NET_RCV_MSG_ID; - msg->msg_hdr.msgh_remote_port = dest; - err = mach_msg ((mach_msg_header_t *)msg, - MACH_SEND_MSG|MACH_SEND_TIMEOUT, - msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL, - 0, MACH_PORT_NULL); - if (err != MACH_MSG_SUCCESS) + if_port_list = &ifp->if_rcv_port_list; + FILTER_ITERATE (if_port_list, infp, nextfp, &infp->input) { - mach_port_deallocate(mach_task_self (), - ((mach_msg_header_t *)msg)->msgh_remote_port); - return err; + mach_port_t dest; + net_hash_entry_t entp, *hash_headp; + int ret_count; + + entp = (net_hash_entry_t) 0; + ret_count = bpf_do_filter (infp, + msg->packet + sizeof (struct packet_header), + msg->net_rcv_msg_packet_count, msg->header, + sizeof (struct ethhdr), &hash_headp, &entp); + if (entp == (net_hash_entry_t) 0) + dest = infp->rcv_port; + else + dest = entp->rcv_port; + + if (ret_count) + { + msg->msg_hdr.msgh_remote_port = dest; + err = mach_msg ((mach_msg_header_t *)msg, + MACH_SEND_MSG|MACH_SEND_TIMEOUT, + msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL, + 0, MACH_PORT_NULL); + if (err != MACH_MSG_SUCCESS) + { + mach_port_deallocate(mach_task_self (), + ((mach_msg_header_t *)msg)->msgh_remote_port); + error (0, err, "mach_msg"); + return -1; + } + } } + FILTER_ITERATE_END - return MACH_MSG_SUCCESS; + return 0; } /* Accept packet SKB received on an interface. */ @@ -241,7 +267,7 @@ netif_rx_handle (char *data, int len, struct net_device *dev) net_msg->header_type = header_type; net_msg->packet_type = packet_type; net_msg->net_rcv_msg_packet_count = ph->length; - deliver_msg (nd->delivery_port, net_msg); + deliver_msg (net_msg, &nd->ifnet.port_list); free (net_msg); } @@ -256,20 +282,18 @@ dev_to_port (void *nd) : MACH_PORT_NULL); } -#if 0 /* * Initialize send and receive queues on an interface. */ void if_init_queues(ifp) register struct ifnet *ifp; { - IFQ_INIT(&ifp->if_snd); - queue_init(&ifp->if_rcv_port_list); - queue_init(&ifp->if_snd_port_list); - simple_lock_init(&ifp->if_rcv_port_list_lock); - simple_lock_init(&ifp->if_snd_port_list_lock); +// IFQ_INIT(&ifp->if_snd); + queue_init(&ifp->port_list.if_rcv_port_list); + queue_init(&ifp->port_list.if_snd_port_list); + mutex_init(&ifp->if_rcv_port_list_lock); + mutex_init(&ifp->if_snd_port_list_lock); } -#endif static io_return_t device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, @@ -279,7 +303,7 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, io_return_t err = D_SUCCESS; struct net_device *dev; struct net_data *nd; -// struct ifnet *ifp; + struct ifnet *ifp; /* Search for the device. */ dev = search_netdev (name); @@ -293,6 +317,8 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, nd = search_nd (dev); if (!nd) { + char *name; + err = create_device_port (sizeof (*nd), &nd); if (err) { @@ -305,23 +331,17 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, nd->device.emul_ops = &linux_net_emulation_ops; nd->next = nd_head; nd_head = nd; -#if 0 - ipc_kobject_set (nd->port, (ipc_kobject_t) & nd->device, IKOT_DEVICE); - notify = ipc_port_make_sonce (nd->port); - ip_lock (nd->port); - ipc_port_nsrequest (nd->port, 1, notify, ¬ify); - assert (notify == IP_NULL); ifp = &nd->ifnet; - ifp->if_unit = dev->name[strlen (dev->name) - 1] - '0'; + name = netdev_name (dev); + ifp->if_unit = name[strlen (name) - 1] - '0'; ifp->if_flags = IFF_UP | IFF_RUNNING; - ifp->if_mtu = dev->mtu; - ifp->if_header_size = dev->hard_header_len; - ifp->if_header_format = dev->type; - ifp->if_address_size = dev->addr_len; - ifp->if_address = dev->dev_addr; + ifp->if_mtu = netdev_mtu (dev); + ifp->if_header_size = netdev_header_len (dev); + ifp->if_header_format = netdev_type (dev); + ifp->if_address_size = netdev_addr_len (dev); + ifp->if_address = netdev_addr (dev); if_init_queues (ifp); -#endif if ((err = dev_open(dev)) < 0) { @@ -425,8 +445,8 @@ device_write (void *d, mach_port_t reply_port, * Other network operations */ static io_return_t -net_getstat(dev, flavor, status, count) - struct net_device *dev; +net_getstat(ifp, flavor, status, count) + struct ifnet *ifp; dev_flavor_t flavor; dev_status_t status; /* pointer to OUT array */ natural_t *count; /* OUT */ @@ -440,12 +460,12 @@ net_getstat(dev, flavor, status, count) if (*count < NET_STATUS_COUNT) return (D_INVALID_OPERATION); - ns->min_packet_size = 60; - ns->max_packet_size = ETH_HLEN + ETHERMTU; - ns->header_format = HDR_ETHERNET; - ns->header_size = ETH_HLEN; - ns->address_size = ETH_ALEN; - ns->flags = 0; + ns->min_packet_size = ifp->if_header_size; + ns->max_packet_size = ifp->if_header_size + ifp->if_mtu; + ns->header_format = ifp->if_header_format; + ns->header_size = ifp->if_header_size; + ns->address_size = ifp->if_address_size; + ns->flags = ifp->if_flags; ns->mapped_size = 0; *count = NET_STATUS_COUNT; @@ -469,7 +489,7 @@ net_getstat(dev, flavor, status, count) return (D_INVALID_OPERATION); } - memcpy(status, netdev_addr(dev), addr_byte_count); + memcpy(status, ifp->if_address, addr_byte_count); if (addr_byte_count < addr_int_count * sizeof(int)) memset((char *)status + addr_byte_count, 0, (addr_int_count * sizeof(int) @@ -556,7 +576,7 @@ device_get_status (void *d, dev_flavor_t flavor, dev_status_t status, #endif { /* common get_status request */ - return net_getstat (net->dev, flavor, status, count); + return net_getstat (&net->ifnet, flavor, status, count); } } @@ -618,12 +638,8 @@ static io_return_t device_set_filter (void *d, mach_port_t port, int priority, filter_t * filter, unsigned filter_count) { - ((struct net_data *) d)->delivery_port = port; - return 0; -#if 0 - return net_set_filter (&((struct net_data *) d)->ifnet, + return net_set_filter (&((struct net_data *) d)->ifnet.port_list, port, priority, filter, filter_count); -#endif } /* Do any initialization required for network devices. */ -- cgit v1.2.3 From 82b5500bf69537c7ce5958346322320b1894e9ae Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Wed, 4 Aug 2010 09:21:22 +0200 Subject: not print errors if fails to deliver packages. --- libmachdev/net.c | 1 - 1 file changed, 1 deletion(-) (limited to 'libmachdev/net.c') diff --git a/libmachdev/net.c b/libmachdev/net.c index 88b1d6c8..606765f5 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -216,7 +216,6 @@ deliver_msg(struct net_rcv_msg *msg, if_filter_list_t *ifp) { mach_port_deallocate(mach_task_self (), ((mach_msg_header_t *)msg)->msgh_remote_port); - error (0, err, "mach_msg"); return -1; } } -- cgit v1.2.3