From 6209bd873a075f01d43d58c67068a215d27c2d45 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 19 Apr 2006 12:07:46 +0000 Subject: First sketch of a new net device API. --- src/net/netdevice.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/net/netdevice.c (limited to 'src/net') diff --git a/src/net/netdevice.c b/src/net/netdevice.c new file mode 100644 index 000000000..d7ad30808 --- /dev/null +++ b/src/net/netdevice.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2006 Michael Brown . + * + * 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 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +/** @file + * + * Network devices and network interfaces + * + */ + +/** List of all registered network devices */ +static LIST_HEAD ( net_devices ); + +/** + * Register network device + * + * @v netdev Network device + * @ret rc Return status code + * + * Adds the network device to the list of network devices. + */ +int register_netdevice ( struct net_device *netdev ) { + list_add ( &netdev->devices, &net_devices ); + return 0; +} + +/** + * Unregister network device + * + * @v netdev Network device + * + * Removes the network device from the list of network devices. + */ +void unregister_netdevice ( struct net_device *netdev ) { + list_del ( &netdev->devices ); +} + +/** + * Transmit packet via network device + * + * @v netdev Network device + * @v pkb Packet buffer + * @ret rc Return status code + * + * Transmits the packet via the network device. The @c pkb link-layer + * metadata must already have been filled in, and space for the + * link-layer header must already be present in the packet buffer. + */ +int netdev_send ( struct net_device *netdev, struct pk_buff *pkb ) { + int rc; + + if ( pkb->net_proto != ETH_P_RAW ) { + if ( ( rc = netdev->build_llh ( netdev, pkb ) ) != 0 ) + return rc; + } + return netdev->transmit ( netdev, pkb ); +} + +/** + * Poll for packet on network device + * + * @v netdev Network device + * @v pkb Packet buffer + * @ret rc Return status code + * + * Polls the network device for a packet. If a packet is available, + * it will be added to the packet buffer, and the link-layer metadata + * fields in @c pkb will be filled in. + */ +int netdev_poll ( struct net_device *netdev, struct pk_buff *pkb ) { + int rc; + + if ( ( rc = netdev->poll ( netdev, pkb ) ) != 0 ) + return rc; + return netdev->parse_llh ( netdev, pkb ); +} + +/** + * Transmit packet via network interface + * + * @v netif Network interface + * @v pkb Packet buffer + * @ret rc Return status code + * + * Transmits the packet via the network interface. The packet must + * start with a network-layer header (e.g. an IP header, for an IP + * interface). The packet contents are undefined on return. + */ +int netif_send ( struct net_interface *netif, struct pk_buff *pkb ) { + struct net_device *netdev = netif->netdev; + int rc; + + if ( ( rc = netif->add_llh_metadata ( netif, pkb ) ) != 0 ) + return rc; + pkb_push ( pkb, netdev->ll_hlen ); + return netdev_send ( netdev, pkb ); +} + +/** + * Process received packet + * + * @v netif Network interface + * @v pkb Packet buffer + * @ret rc Return status code + * + * Processes a packet received via netdev_poll(). The interface + * corresponding to the network-layer protocol is identified, the + * link-layer header is stripped from the packet and the packet is + * passed to the net_interface::rx_packet() method. + */ +int netdev_rx_packet ( struct net_device *netdev, struct pk_buff *pkb ) { + struct net_interface *netif; + + netif = netdev_find_netif ( netdev, pkb->net_proto ); + if ( ! netif ) + return -EAFNOSUPPORT; + + pkb_pull ( pkb, netdev->ll_hlen ); + return netif->rx_packet ( netif, pkb ); +} + +/** + * Poll for packet on all network devices + * + * @v pkb Packet buffer + * @ret netdev Network device + * @ret rc Return status code + * + * Polls all network devices for a packet. If a packet is available + * on any interface, @c netdev will be filled in and the packet will + * be received as per netdev_poll(). + */ +int net_poll ( struct pk_buff *pkb, struct net_device **netdev ) { + int rc; + + list_for_each_entry ( (*netdev), &net_devices, devices ) { + if ( ( rc = netdev_poll ( *netdev, pkb ) ) == 0 ) + return rc; + } + + return -EAGAIN; +} -- cgit v1.2.3-55-g7522