diff --git a/src/include/gpxe/arp.h b/src/include/gpxe/arp.h index a2db80f1..27591d3f 100644 --- a/src/include/gpxe/arp.h +++ b/src/include/gpxe/arp.h @@ -7,10 +7,12 @@ * */ +struct net_device; struct net_header; struct ll_header; -extern int arp_resolve ( const struct net_header *nethdr, +extern int arp_resolve ( struct net_device *netdev, + const struct net_header *nethdr, struct ll_header *llhdr ); #endif /* _GPXE_ARP_H */ diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h index f7d78288..6db95bbb 100644 --- a/src/include/gpxe/netdevice.h +++ b/src/include/gpxe/netdevice.h @@ -11,12 +11,16 @@ #include struct pk_buff; +struct net_device; struct net_protocol; struct ll_protocol; /** Maximum length of a link-layer address */ #define MAX_LL_ADDR_LEN 6 +/** Maximum length of a link-layer header */ +#define MAX_LL_HEADER_LEN 16 + /** Maximum length of a network-layer address */ #define MAX_NET_ADDR_LEN 4 @@ -32,37 +36,37 @@ struct ll_protocol; struct net_header { /** Network-layer protocol */ struct net_protocol *net_protocol; - /** Destination address flags + /** Flags * - * This is the bitwise OR of zero or more NETADDR_FL_XXX + * This is the bitwise OR of zero or more PKT_FL_XXX * values. */ - int dest_flags; + int flags; /** Network-layer destination address */ uint8_t dest_net_addr[MAX_NET_ADDR_LEN]; /** Network-layer source address */ uint8_t source_net_addr[MAX_NET_ADDR_LEN]; }; -/** Address is a broadcast address */ -#define NETADDR_FL_BROADCAST 0x01 +/** Packet is a broadcast packet */ +#define PKT_FL_BROADCAST 0x01 -/** Address is a multicast address */ -#define NETADDR_FL_MULTICAST 0x02 +/** Packet is a multicast packet */ +#define PKT_FL_MULTICAST 0x02 -/** Address is a raw hardware address */ -#define NETADDR_FL_RAW 0x04 +/** Addresses are raw hardware addresses */ +#define PKT_FL_RAW_ADDR 0x04 /** A generic link-layer header */ struct ll_header { /** Link-layer protocol */ struct ll_protocol *ll_protocol; - /** Destination address flags + /** Flags * - * This is the bitwise OR of zero or more NETADDR_FL_XXX + * This is the bitwise OR of zero or more PKT_FL_XXX * values. */ - int dest_flags; + int flags; /** Link-layer destination address */ uint8_t dest_ll_addr[MAX_LL_ADDR_LEN]; /** Link-layer source address */ @@ -80,21 +84,21 @@ struct ll_header { * */ struct net_protocol { + /** Protocol name */ + const char *name; /** * Perform network-layer routing * * @v pkb Packet buffer - * @ret source Network-layer source address - * @ret dest Network-layer destination address + * @v nethdr Generic network-layer header * @ret rc Return status code * - * This method should fill in the source and destination - * addresses with enough information to allow the link layer - * to route the packet. + * This method should fill in the network header with enough + * information to allow the link layer to route the packet. * * For example, in the case of IPv4, this method should fill - * in @c source with the IP addresses of the local adapter and - * @c dest with the next hop destination (e.g. the gateway). + * in the IP addresses of the local adapter and the next hop + * destination (e.g. the gateway). */ int ( * route ) ( const struct pk_buff *pkb, struct net_header *nethdr ); @@ -108,6 +112,19 @@ struct net_protocol { * the packet buffer. */ int ( * rx ) ( struct pk_buff *pkb ); + /** + * Transcribe network-layer address + * + * @v net_addr Network-layer address + * @ret string Human-readable transcription of address + * + * This method should convert the network-layer address into a + * human-readable format (e.g. dotted quad notation for IPv4). + * + * The buffer used to hold the transcription is statically + * allocated. + */ + const char * ( *ntoa ) ( const void * net_addr ); /** Network-layer protocol * * This is an ETH_P_XXX constant, in network-byte order @@ -122,9 +139,12 @@ struct net_protocol { * */ struct ll_protocol { + /** Protocol name */ + const char *name; /** * Perform link-layer routing * + * @v netdev Network device * @v nethdr Generic network-layer header * @ret llhdr Generic link-layer header * @ret rc Return status code @@ -137,7 +157,8 @@ struct ll_protocol { * return an error (after transmitting an ARP request, if * applicable). */ - int ( * route ) ( const struct net_header *nethdr, + int ( * route ) ( struct net_device *netdev, + const struct net_header *nethdr, struct ll_header *llhdr ); /** * Fill media-specific link-layer header @@ -164,6 +185,19 @@ struct ll_protocol { void ( * parse_llh ) ( const struct pk_buff *pkb, struct ll_header *llhdr ); + /** + * Transcribe link-layer address + * + * @v ll_addr Link-layer address + * @ret string Human-readable transcription of address + * + * This method should convert the link-layer address into a + * human-readable format. + * + * The buffer used to hold the transcription is statically + * allocated. + */ + const char * ( *ntoa ) ( const void * ll_addr ); /** Link-layer protocol * * This is an ARPHRD_XXX constant, in network byte order. @@ -290,13 +324,30 @@ free_netdev ( struct net_device *netdev __attribute__ (( unused )) ) { /* Nothing to do */ } +/** + * Transmit raw packet via network device + * + * @v netdev Network device + * @v pkb Packet buffer + * @ret rc Return status code + * + * Transmits the packet via the specified network device. The + * link-layer header must already have been filled in. If this + * function returns success, it has taken ownership of the packet + * buffer. + */ +static inline int netdev_transmit ( struct net_device *netdev, + struct pk_buff *pkb ) { + return netdev->transmit ( netdev, pkb ); +} + /** * Register a link-layer protocol * * @v protocol Link-layer protocol */ #define LL_PROTOCOL( protocol ) \ - struct ll_protocol protocol __table ( ll_protocols, 00 ) + struct ll_protocol protocol __table ( ll_protocols, 01 ) /** * Register a network-layer protocol @@ -304,7 +355,7 @@ free_netdev ( struct net_device *netdev __attribute__ (( unused )) ) { * @v protocol Network-layer protocol */ #define NET_PROTOCOL( protocol ) \ - struct net_protocol protocol __table ( net_protocols, 00 ) + struct net_protocol protocol __table ( net_protocols, 01 ) /** * Register a network-layer address for the static single network device @@ -312,15 +363,17 @@ free_netdev ( struct net_device *netdev __attribute__ (( unused )) ) { * @v net_address Network-layer address */ #define STATIC_SINGLE_NETDEV_ADDRESS( address ) \ - struct net_address address __table ( sgl_netdev_addresses, 00 ) + struct net_address address __table ( sgl_netdev_addresses, 01 ) -extern struct net_protocol *net_find_protocol ( uint16_t net_proto ); -extern struct net_device * net_find_address ( struct net_protocol *net_proto, - void *net_addr ); +extern void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ); +extern struct net_protocol *find_net_protocol ( uint16_t net_proto ); +extern struct net_device * +find_netdev_by_net_addr ( struct net_protocol *net_protocol, void *net_addr ); + +extern int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ); extern int net_transmit ( struct pk_buff *pkb ); extern int net_poll ( void ); -extern void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ); extern struct pk_buff * net_rx_dequeue ( void ); #endif /* _GPXE_NETDEVICE_H */ diff --git a/src/net/arp.c b/src/net/arp.c index a375eec9..3720acfc 100644 --- a/src/net/arp.c +++ b/src/net/arp.c @@ -91,6 +91,7 @@ arp_find_entry ( struct ll_protocol *ll_protocol, /** * Look up media-specific link-layer address in the ARP cache * + * @v netdev Network device * @v nethdr Generic network-layer header * @ret llhdr Generic link-layer header * @ret rc Return status code @@ -102,9 +103,11 @@ arp_find_entry ( struct ll_protocol *ll_protocol, * llhdr. * * If no address is found in the ARP cache, an ARP request will be - * transmitted and -ENOENT will be returned. + * transmitted on the specified network device and -ENOENT will be + * returned. */ -int arp_resolve ( const struct net_header *nethdr, struct ll_header *llhdr ) { +int arp_resolve ( struct net_device *netdev, const struct net_header *nethdr, + struct ll_header *llhdr ) { struct net_protocol *net_protocol = nethdr->net_protocol; struct ll_protocol *ll_protocol = llhdr->ll_protocol; const struct arp_entry *arp; @@ -116,17 +119,23 @@ int arp_resolve ( const struct net_header *nethdr, struct ll_header *llhdr ) { arp = arp_find_entry ( ll_protocol, net_protocol, nethdr->dest_net_addr ); if ( arp ) { + DBG ( "ARP cache hit: %s %s => %s %s\n", + net_protocol->name, net_protocol->ntoa ( arp->net_addr ), + ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) ); memcpy ( llhdr->dest_ll_addr, arp->ll_addr, sizeof ( llhdr->dest_ll_addr ) ); return 0; } + DBG ( "ARP cache miss: %s %s\n", net_protocol->name, + net_protocol->ntoa ( nethdr->dest_net_addr ) ); /* Allocate ARP packet */ - pkb = alloc_pkb ( sizeof ( *arphdr ) + + pkb = alloc_pkb ( MAX_LL_HEADER_LEN + sizeof ( *arphdr ) + 2 * ( MAX_LL_ADDR_LEN + MAX_NET_ADDR_LEN ) ); if ( ! pkb ) return -ENOMEM; pkb->net_protocol = &arp_protocol; + pkb_reserve ( pkb, MAX_LL_HEADER_LEN ); /* Build up ARP request */ arphdr = pkb_put ( pkb, sizeof ( *arphdr ) ); @@ -145,7 +154,7 @@ int arp_resolve ( const struct net_header *nethdr, struct ll_header *llhdr ) { nethdr->dest_net_addr, net_protocol->net_addr_len ); /* Transmit ARP request */ - if ( ( rc = net_transmit ( pkb ) ) != 0 ) { + if ( ( rc = net_transmit_via ( pkb, netdev ) ) != 0 ) { free_pkb ( pkb ); return rc; } @@ -175,7 +184,7 @@ static int arp_rx ( struct pk_buff *pkb ) { /* Identify link-layer and network-layer protocols */ ll_protocol = pkb->ll_protocol; - net_protocol = net_find_protocol ( arphdr->ar_pro ); + net_protocol = find_net_protocol ( arphdr->ar_pro ); if ( ! net_protocol ) goto done; @@ -192,10 +201,14 @@ static int arp_rx ( struct pk_buff *pkb ) { memcpy ( arp->ll_addr, arp_sender_ha ( arphdr ), arphdr->ar_hln ); merge = 1; + DBG ( "ARP cache update: %s %s => %s %s\n", + net_protocol->name, net_protocol->ntoa ( arp->net_addr ), + ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) ); } /* See if we own the target protocol address */ - netdev = net_find_address ( net_protocol, arp_target_pa ( arphdr ) ); + netdev = find_netdev_by_net_addr ( net_protocol, + arp_target_pa ( arphdr ) ); if ( ! netdev ) goto done; @@ -208,6 +221,9 @@ static int arp_rx ( struct pk_buff *pkb ) { arphdr->ar_hln ); memcpy ( arp->net_addr, arp_sender_pa ( arphdr ), arphdr->ar_pln); + DBG ( "ARP cache add: %s %s => %s %s\n", + net_protocol->name, net_protocol->ntoa ( arp->net_addr ), + ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) ); } /* If it's not a request, there's nothing more to do */ @@ -215,11 +231,14 @@ static int arp_rx ( struct pk_buff *pkb ) { goto done; /* Change request to a reply, and send it */ + DBG ( "ARP reply: %s %s => %s %s\n", net_protocol->name, + net_protocol->ntoa ( arp_target_pa ( arphdr ) ), + ll_protocol->name, ll_protocol->ntoa ( netdev->ll_addr ) ); arphdr->ar_op = htons ( ARPOP_REPLY ); memswap ( arp_sender_ha ( arphdr ), arp_target_ha ( arphdr ), arphdr->ar_hln + arphdr->ar_pln ); memcpy ( arp_target_ha ( arphdr ), netdev->ll_addr, arphdr->ar_hln ); - if ( net_transmit ( pkb ) == 0 ) + if ( net_transmit_via ( pkb, netdev ) == 0 ) pkb = NULL; done: @@ -243,18 +262,33 @@ static int arp_route ( const struct pk_buff *pkb, arphdr->ar_hln ); memcpy ( nethdr->dest_net_addr, arp_target_ha ( arphdr ), arphdr->ar_hln ); - nethdr->dest_flags = NETADDR_FL_RAW; + nethdr->flags = PKT_FL_RAW_ADDR; if ( arphdr->ar_op == htons ( ARPOP_REQUEST ) ) - nethdr->dest_flags |= NETADDR_FL_BROADCAST; + nethdr->flags |= PKT_FL_BROADCAST; return 0; } +/** + * Transcribe ARP address + * + * @v net_addr ARP address + * @ret string "" + * + * This operation is meaningless for the ARP protocol. + */ +static const char * +arp_ntoa ( const void *net_addr __attribute__ (( unused )) ) { + return ""; +} + /** ARP protocol */ struct net_protocol arp_protocol = { + .name = "ARP", .net_proto = htons ( ETH_P_ARP ), .rx = arp_rx, .route = arp_route, + .ntoa = arp_ntoa, }; NET_PROTOCOL ( arp_protocol ); diff --git a/src/net/ethernet.c b/src/net/ethernet.c index 59b469f1..cf0ddd7d 100644 --- a/src/net/ethernet.c +++ b/src/net/ethernet.c @@ -51,16 +51,21 @@ static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; * is sent for the requested network-layer address and -ENOENT is * returned. */ -static int eth_route ( const struct net_header *nethdr, +static int eth_route ( struct net_device *netdev, + const struct net_header *nethdr, struct ll_header *llhdr ) { int rc; + /* Fill in the easy bits */ + llhdr->net_proto = nethdr->net_protocol->net_proto; + memcpy ( llhdr->source_ll_addr, netdev->ll_addr, ETH_ALEN ); + /* Work out the destination MAC address */ - if ( nethdr->dest_flags & NETADDR_FL_RAW ) { - memcpy ( llhdr->dest_ll_addr, nethdr->dest_net_addr, ETH_ALEN); - } else if ( nethdr->dest_flags & NETADDR_FL_BROADCAST ) { + if ( nethdr->flags & PKT_FL_BROADCAST ) { memcpy ( llhdr->dest_ll_addr, eth_broadcast, ETH_ALEN ); - } else if ( nethdr->dest_flags & NETADDR_FL_MULTICAST ) { + } else if ( nethdr->flags & PKT_FL_RAW_ADDR ) { + memcpy ( llhdr->dest_ll_addr, nethdr->dest_net_addr, ETH_ALEN); + } else if ( nethdr->flags & PKT_FL_MULTICAST ) { /* IP multicast is a special case; there exists a * direct mapping from IP address to MAC address */ @@ -73,7 +78,7 @@ static int eth_route ( const struct net_header *nethdr, llhdr->dest_ll_addr[5] = nethdr->dest_net_addr[3]; } else { /* Otherwise, look up the address using ARP */ - if ( ( rc = arp_resolve ( nethdr, llhdr ) ) != 0 ) + if ( ( rc = arp_resolve ( netdev, nethdr, llhdr ) ) != 0 ) return rc; } @@ -116,22 +121,40 @@ static void eth_parse_llh ( const struct pk_buff *pkb, llhdr->net_proto = ethhdr->h_protocol; if ( memcmp ( ethhdr->h_dest, eth_broadcast, ETH_ALEN ) == 0 ) { - llhdr->dest_flags = NETADDR_FL_BROADCAST; + llhdr->flags = PKT_FL_BROADCAST; } else if ( ethhdr->h_dest[0] & 0x01 ) { - llhdr->dest_flags = NETADDR_FL_MULTICAST; + llhdr->flags = PKT_FL_MULTICAST; } else { - llhdr->dest_flags = 0; + llhdr->flags = 0; } } +/** + * Transcribe Ethernet address + * + * @v ll_addr Link-layer address + * @ret string Link-layer address in human-readable format + */ +static const char * eth_ntoa ( const void *ll_addr ) { + static char buf[18]; /* "00:00:00:00:00:00" */ + uint8_t *eth_addr = ll_addr; + + sprintf ( buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + eth_addr[0], eth_addr[1], eth_addr[2], + eth_addr[3], eth_addr[4], eth_addr[5] ); + return buf; +} + /** Ethernet protocol */ struct ll_protocol ethernet_protocol = { + .name = "Ethernet", .ll_proto = htons ( ARPHRD_ETHER ), .ll_addr_len = ETH_ALEN, .ll_header_len = ETH_HLEN, .route = eth_route, .fill_llh = eth_fill_llh, .parse_llh = eth_parse_llh, + .ntoa = eth_ntoa, }; LL_PROTOCOL ( ethernet_protocol ); diff --git a/src/net/ipv4.c b/src/net/ipv4.c index 4200d234..2fc50672 100644 --- a/src/net/ipv4.c +++ b/src/net/ipv4.c @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -153,7 +154,8 @@ static int ipv4_rx ( struct pk_buff *pkb ) { /* Transfer to uIP buffer. Horrendously space-inefficient, * but will do as a proof-of-concept for now. */ - memcpy ( uip_buf, pkb->data, pkb_len ( pkb ) ); + uip_len = pkb_len ( pkb ); + memcpy ( uip_buf, pkb->data, uip_len ); /* Hand to uIP for processing */ uip_input (); @@ -198,22 +200,40 @@ static int ipv4_route ( const struct pk_buff *pkb, } /* Set broadcast and multicast flags as applicable */ - nethdr->dest_flags = 0; + nethdr->flags = 0; if ( dest->s_addr == htonl ( INADDR_BROADCAST ) ) { - nethdr->dest_flags = NETADDR_FL_BROADCAST; + nethdr->flags = PKT_FL_BROADCAST; } else if ( IN_MULTICAST ( dest->s_addr ) ) { - nethdr->dest_flags = NETADDR_FL_MULTICAST; + nethdr->flags = PKT_FL_MULTICAST; } return 0; } +/** + * Transcribe IP address + * + * @v net_addr IP address + * @ret string IP address in dotted-quad notation + * + */ +static const char * ipv4_ntoa ( const void *net_addr ) { + static char buf[16]; /* "xxx.xxx.xxx.xxx" */ + uint8_t *ip_addr = net_addr; + + sprintf ( buf, "%d.%d.%d.%d", ip_addr[0], ip_addr[1], ip_addr[2], + ip_addr[3] ); + return buf; +} + /** IPv4 protocol */ struct net_protocol ipv4_protocol = { - .net_proto = ETH_P_IP, + .name = "IP", + .net_proto = htons ( ETH_P_IP ), .net_addr_len = sizeof ( struct in_addr ), .rx = ipv4_rx, .route = ipv4_route, + .ntoa = ipv4_ntoa, }; NET_PROTOCOL ( ipv4_protocol ); @@ -221,6 +241,18 @@ NET_PROTOCOL ( ipv4_protocol ); /** IPv4 address for the static single net device */ struct net_address static_single_ipv4_address = { .net_protocol = &ipv4_protocol, + +#warning "Remove this static-IP hack" + .net_addr = { 0x0a, 0xfe, 0xfe, 0x01 }, }; STATIC_SINGLE_NETDEV_ADDRESS ( static_single_ipv4_address ); + +#warning "Remove this static-IP hack" +static struct ipv4_route routing_table[NUM_ROUTES] = { + { { htonl ( 0x0afefe00 ) }, { htonl ( 0xfffffffc ) }, + { htonl ( 0x00000000 ) }, { htonl ( 0x0afefe01 ) } }, + { { htonl ( 0x00000000 ) }, { htonl ( 0x00000000 ) }, + { htonl ( 0x0afefe02 ) }, { htonl ( 0x0afefe01 ) } }, +}; + 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 @@ -60,6 +60,22 @@ static struct net_address static_single_netdev_addresses_end[0] /** Recevied packet queue */ 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 * @@ -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,9 +123,77 @@ struct net_device * net_find_address ( struct net_protocol *net_protocol, net_protocol->net_addr_len ) == 0 ) ) return netdev; } + return NULL; } +/** + * 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 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_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; + int rc; + + /* Perform network-layer routing */ + net_protocol = pkb->net_protocol; + nethdr.net_protocol = net_protocol; + 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, 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; + 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 ) { + DBG ( "Device failed to transmit packet\n" ); + return rc; + } + + DBG ( "Packet transmitted\n" ); + return 0; +} + /** * Transmit packet * @@ -120,46 +205,7 @@ struct net_device * net_find_address ( struct net_protocol *net_protocol, * buffer. */ int net_transmit ( struct pk_buff *pkb ) { - 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; - - /* Identify transmitting network device */ - netdev = net_find_address ( net_protocol, nethdr.source_net_addr ); - if ( ! netdev ) - goto err; - - /* 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; - - /* 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; - - return 0; - - err: - free_pkb ( pkb ); - return rc; + return net_transmit_via ( pkb, NULL ); } /** @@ -174,26 +220,12 @@ 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 * @@ -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" ); } }