diff options
Diffstat (limited to 'libmachdev')
-rw-r--r-- | libmachdev/Makefile | 2 | ||||
-rw-r--r-- | libmachdev/if_hdr.h | 165 | ||||
-rw-r--r-- | libmachdev/mach_glue.h | 7 | ||||
-rw-r--r-- | libmachdev/net.c | 118 |
4 files changed, 240 insertions, 52 deletions
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 <queue.h> +#include <cthreads.h> +#include <bpf_impl.h> + +#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 <assert.h> #include <string.h> #include <arpa/inet.h> +#include <error.h> #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. */ |