david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Network layer now works as a proof of concept

This commit is contained in:
Michael Brown 2006-04-28 14:13:50 +00:00
parent 1488cd3b73
commit 129c6c3968
6 changed files with 291 additions and 111 deletions

View File

@ -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 */

View File

@ -11,12 +11,16 @@
#include <gpxe/tables.h>
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 */

View File

@ -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 "<ARP>"
*
* This operation is meaningless for the ARP protocol.
*/
static const char *
arp_ntoa ( const void *net_addr __attribute__ (( unused )) ) {
return "<ARP>";
}
/** 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 );

View File

@ -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 );

View File

@ -1,6 +1,7 @@
#include <string.h>
#include <stdint.h>
#include <byteswap.h>
#include <vsprintf.h>
#include <gpxe/in.h>
@ -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 ) } },
};

View File

@ -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" );
}
}