diff options
author | Michael Brown | 2006-04-28 16:13:50 +0200 |
---|---|---|
committer | Michael Brown | 2006-04-28 16:13:50 +0200 |
commit | 129c6c3968d4967f091266ee8c7d99986080e201 (patch) | |
tree | 619664ae529782f67bb6d5832443b21001a4c811 /src/net/netdevice.c | |
parent | Fix a couple of broken assertions, and align the buffer correctly. (diff) | |
download | ipxe-129c6c3968d4967f091266ee8c7d99986080e201.tar.gz ipxe-129c6c3968d4967f091266ee8c7d99986080e201.tar.xz ipxe-129c6c3968d4967f091266ee8c7d99986080e201.zip |
Network layer now works as a proof of concept
Diffstat (limited to 'src/net/netdevice.c')
-rw-r--r-- | src/net/netdevice.c | 118 |
1 files changed, 77 insertions, 41 deletions
diff --git a/src/net/netdevice.c b/src/net/netdevice.c index 3ff6657c..59861d05 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -61,6 +61,22 @@ static struct net_address static_single_netdev_addresses_end[0] static LIST_HEAD ( rx_queue ); /** + * Add packet to receive queue + * + * @v netdev Network device + * @v pkb Packet buffer + * + * The packet is added to the RX queue. Ownership of the packet is + * transferred to the RX queue; the caller must not touch the packet + * buffer after calling netdev_rx(). + */ +void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) { + DBG ( "Packet received\n" ); + pkb->ll_protocol = netdev->ll_protocol; + list_add_tail ( &pkb->list, &rx_queue ); +} + +/** * Identify network protocol * * @v net_proto Network-layer protocol, in network-byte order @@ -69,7 +85,7 @@ static LIST_HEAD ( rx_queue ); * Identify a network-layer protocol from a protocol number, which * must be an ETH_P_XXX constant in network-byte order. */ -struct net_protocol * net_find_protocol ( uint16_t net_proto ) { +struct net_protocol * find_net_protocol ( uint16_t net_proto ) { struct net_protocol *net_protocol; for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ; @@ -93,8 +109,9 @@ struct net_protocol * net_find_protocol ( uint16_t net_proto ) { * Note that even with a static single network device, this function * can still return NULL. */ -struct net_device * net_find_address ( struct net_protocol *net_protocol, - void *net_addr ) { +struct net_device * +find_netdev_by_net_addr ( struct net_protocol *net_protocol, + void *net_addr ) { struct net_address *net_address; struct net_device *netdev = &static_single_netdev; @@ -106,60 +123,89 @@ struct net_device * net_find_address ( struct net_protocol *net_protocol, net_protocol->net_addr_len ) == 0 ) ) return netdev; } + return NULL; } /** - * Transmit packet + * Transmit packet via a network device * * @v pkb Packet buffer + * @v netdev Network device, or NULL * @ret rc Return status code * - * Transmits the packet via the appropriate network device. If this + * Transmits the packet via the specified network device. The packet + * must begin with a network-layer header, and the @c net_protocol + * field must have been filled in. If @c netdev is NULL, the network + * device is identified via the packet contents, if possible. If this * function returns success, it has taken ownership of the packet * buffer. */ -int net_transmit ( struct pk_buff *pkb ) { +int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) { struct net_protocol *net_protocol; struct net_header nethdr; struct ll_protocol *ll_protocol; struct ll_header llhdr; - struct net_device *netdev; int rc; /* Perform network-layer routing */ net_protocol = pkb->net_protocol; nethdr.net_protocol = net_protocol; - if ( ( rc = net_protocol->route ( pkb, &nethdr ) ) != 0 ) - goto err; + if ( ( rc = net_protocol->route ( pkb, &nethdr ) ) != 0 ) { + DBG ( "Could not route to %s address %s\n", + net_protocol->name, + net_protocol->ntoa ( nethdr.dest_net_addr ) ); + return rc; + } - /* Identify transmitting network device */ - netdev = net_find_address ( net_protocol, nethdr.source_net_addr ); - if ( ! netdev ) - goto err; + /* Identify transmitting network device, if not specified */ + if ( ! netdev ) { + netdev = find_netdev_by_net_addr ( net_protocol, + nethdr.source_net_addr ); + if ( ! netdev ) { + DBG ( "No network device for %s address %s\n", + net_protocol->name, + net_protocol->ntoa ( nethdr.source_net_addr ) ); + return -EHOSTUNREACH; + } + } /* Perform link-layer routing */ ll_protocol = netdev->ll_protocol; llhdr.ll_protocol = ll_protocol; - llhdr.net_proto = net_protocol->net_proto; - memcpy ( llhdr.source_ll_addr, netdev->ll_addr, - ll_protocol->ll_addr_len); - if ( ( rc = ll_protocol->route ( &nethdr, &llhdr ) ) != 0 ) - goto err; + if ( ( rc = ll_protocol->route ( netdev, &nethdr, &llhdr ) ) != 0 ) { + DBG ( "No link-layer route to %s address %s\n", + net_protocol->name, + net_protocol->ntoa ( nethdr.dest_net_addr ) ); + return rc; + } /* Prepend link-layer header */ pkb_push ( pkb, ll_protocol->ll_header_len ); ll_protocol->fill_llh ( &llhdr, pkb ); /* Transmit packet */ - if ( ( rc = netdev->transmit ( netdev, pkb ) ) != 0 ) - goto err; - + if ( ( rc = netdev->transmit ( netdev, pkb ) ) != 0 ) { + DBG ( "Device failed to transmit packet\n" ); + return rc; + } + + DBG ( "Packet transmitted\n" ); return 0; +} - err: - free_pkb ( pkb ); - return rc; +/** + * Transmit packet + * + * @v pkb Packet buffer + * @ret rc Return status code + * + * Transmits the packet via the appropriate network device. If this + * function returns success, it has taken ownership of the packet + * buffer. + */ +int net_transmit ( struct pk_buff *pkb ) { + return net_transmit_via ( pkb, NULL ); } /** @@ -174,27 +220,13 @@ int net_transmit ( struct pk_buff *pkb ) { int net_poll ( void ) { struct net_device *netdev = &static_single_netdev; + DBG ( "Polling network\n" ); netdev->poll ( netdev ); return ( ! list_empty ( &rx_queue ) ); } /** - * Add packet to receive queue - * - * @v netdev Network device - * @v pkb Packet buffer - * - * The packet is added to the RX queue. Ownership of the packet is - * transferred to the RX queue; the caller must not touch the packet - * buffer after calling netdev_rx(). - */ -void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) { - pkb->ll_protocol = netdev->ll_protocol; - list_add_tail ( &pkb->list, &rx_queue ); -} - -/** * Remove packet from receive queue * * @ret pkb Packet buffer, or NULL @@ -225,22 +257,26 @@ void net_run ( void ) { ll_protocol->parse_llh ( pkb, &llhdr ); /* Identify network-layer protocol */ - net_protocol = net_find_protocol ( llhdr.net_proto ); + net_protocol = find_net_protocol ( llhdr.net_proto ); if ( ! net_protocol ) { - DBG ( "Unknown network-layer protocol %02x\n", + DBG ( "Unknown network-layer protocol %x\n", ntohs ( llhdr.net_proto ) ); free_pkb ( pkb ); continue; } + pkb->net_protocol = net_protocol; /* Strip off link-layer header */ pkb_pull ( pkb, ll_protocol->ll_header_len ); /* Hand off to network layer */ if ( net_protocol->rx ( pkb ) != 0 ) { + DBG ( "Network-layer protocol refused packet\n" ); free_pkb ( pkb ); continue; } + + DBG ( "Processed received packet\n" ); } } |