mirror of
https://github.com/xcat2/xNBA.git
synced 2024-12-23 19:51:46 +00:00
Change semantics of network API so that packet-absorbing calls *always*
take ownership of the packet, rather than doing so only if they return success. This breaks semantic compatibility with Linux's hard_start_xmit() method, but means that we don't have to worry so much about error cases. Split mechanism of processing received packets (net_rx_process()) out from policy (net_step()), preparatory to putting net_step() in a separate object.
This commit is contained in:
parent
23c494d14e
commit
bac97eb979
@ -103,15 +103,14 @@ struct net_protocol {
|
||||
int ( * route ) ( const struct pk_buff *pkb,
|
||||
struct net_header *nethdr );
|
||||
/**
|
||||
* Handle received packets
|
||||
* Process received packet
|
||||
*
|
||||
* @v pkb Packet buffer
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* If this method returns success, it has taken ownership of
|
||||
* the packet buffer.
|
||||
* This method takes ownership of the packet buffer.
|
||||
*/
|
||||
int ( * rx ) ( struct pk_buff *pkb );
|
||||
int ( * rx_process ) ( struct pk_buff *pkb );
|
||||
/**
|
||||
* Transcribe network-layer address
|
||||
*
|
||||
@ -240,9 +239,9 @@ struct net_device {
|
||||
* This method should cause the hardware to initiate
|
||||
* transmission of the packet buffer.
|
||||
*
|
||||
* If the method returns success, ownership of the packet
|
||||
* buffer is transferred to the @c net_device, which must
|
||||
* eventually call free_pkb() to release the buffer.
|
||||
* Ownership of the packet buffer is transferred to the @c
|
||||
* net_device, which must eventually call free_pkb() to
|
||||
* release the buffer.
|
||||
*/
|
||||
int ( * transmit ) ( struct net_device *netdev, struct pk_buff *pkb );
|
||||
/** Poll for received packet
|
||||
@ -332,9 +331,8 @@ free_netdev ( struct net_device *netdev __attribute__ (( unused )) ) {
|
||||
* @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.
|
||||
* link-layer header must already have been filled in. This function
|
||||
* takes ownership of the packet buffer.
|
||||
*/
|
||||
static inline int netdev_transmit ( struct net_device *netdev,
|
||||
struct pk_buff *pkb ) {
|
||||
@ -375,5 +373,6 @@ 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 struct pk_buff * net_rx_dequeue ( void );
|
||||
extern int net_rx_process ( struct pk_buff *pkb );
|
||||
|
||||
#endif /* _GPXE_NETDEVICE_H */
|
||||
|
@ -154,10 +154,8 @@ int arp_resolve ( struct net_device *netdev, const struct net_header *nethdr,
|
||||
nethdr->dest_net_addr, net_protocol->net_addr_len );
|
||||
|
||||
/* Transmit ARP request */
|
||||
if ( ( rc = net_transmit_via ( pkb, netdev ) ) != 0 ) {
|
||||
free_pkb ( pkb );
|
||||
if ( ( rc = net_transmit_via ( pkb, netdev ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
@ -230,7 +228,7 @@ static int arp_rx ( struct pk_buff *pkb ) {
|
||||
if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) )
|
||||
goto done;
|
||||
|
||||
/* Change request to a reply, and send it */
|
||||
/* Change request to a reply */
|
||||
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 ) );
|
||||
@ -238,8 +236,10 @@ static int arp_rx ( struct pk_buff *pkb ) {
|
||||
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_via ( pkb, netdev ) == 0 )
|
||||
pkb = NULL;
|
||||
|
||||
/* Send reply */
|
||||
net_transmit_via ( pkb, netdev );
|
||||
pkb = NULL;
|
||||
|
||||
done:
|
||||
free_pkb ( pkb );
|
||||
@ -286,7 +286,7 @@ arp_ntoa ( const void *net_addr __attribute__ (( unused )) ) {
|
||||
struct net_protocol arp_protocol = {
|
||||
.name = "ARP",
|
||||
.net_proto = htons ( ETH_P_ARP ),
|
||||
.rx = arp_rx,
|
||||
.rx_process = arp_rx,
|
||||
.route = arp_route,
|
||||
.ntoa = arp_ntoa,
|
||||
};
|
||||
|
@ -163,8 +163,7 @@ static int ipv4_rx ( struct pk_buff *pkb ) {
|
||||
pkb_empty ( pkb );
|
||||
pkb_put ( pkb, uip_len );
|
||||
memcpy ( pkb->data, uip_buf, uip_len );
|
||||
if ( net_transmit ( pkb ) != 0 )
|
||||
free_pkb ( pkb );
|
||||
net_transmit ( pkb );
|
||||
} else {
|
||||
free_pkb ( pkb );
|
||||
}
|
||||
@ -231,7 +230,7 @@ struct net_protocol ipv4_protocol = {
|
||||
.name = "IP",
|
||||
.net_proto = htons ( ETH_P_IP ),
|
||||
.net_addr_len = sizeof ( struct in_addr ),
|
||||
.rx = ipv4_rx,
|
||||
.rx_process = ipv4_rx,
|
||||
.route = ipv4_route,
|
||||
.ntoa = ipv4_ntoa,
|
||||
};
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <gpxe/if_ether.h>
|
||||
#include <gpxe/pkbuff.h>
|
||||
#include <gpxe/tables.h>
|
||||
#include <gpxe/process.h>
|
||||
#include <gpxe/netdevice.h>
|
||||
|
||||
/** @file
|
||||
@ -66,9 +67,8 @@ static LIST_HEAD ( rx_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().
|
||||
* The packet is added to the RX queue. This function takes ownership
|
||||
* of the packet buffer.
|
||||
*/
|
||||
void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) {
|
||||
DBG ( "Packet received\n" );
|
||||
@ -137,9 +137,8 @@ find_netdev_by_net_addr ( struct net_protocol *net_protocol,
|
||||
* 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.
|
||||
* device is identified via the packet contents, if possible. This
|
||||
* function takes ownership of the packet buffer.
|
||||
*/
|
||||
int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
||||
struct net_protocol *net_protocol;
|
||||
@ -155,6 +154,7 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
||||
DBG ( "Could not route to %s address %s\n",
|
||||
net_protocol->name,
|
||||
net_protocol->ntoa ( nethdr.dest_net_addr ) );
|
||||
free_pkb ( pkb );
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -166,6 +166,7 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
||||
DBG ( "No network device for %s address %s\n",
|
||||
net_protocol->name,
|
||||
net_protocol->ntoa ( nethdr.source_net_addr ) );
|
||||
free_pkb ( pkb );
|
||||
return -EHOSTUNREACH;
|
||||
}
|
||||
}
|
||||
@ -177,6 +178,7 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
||||
DBG ( "No link-layer route to %s address %s\n",
|
||||
net_protocol->name,
|
||||
net_protocol->ntoa ( nethdr.dest_net_addr ) );
|
||||
free_pkb ( pkb );
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -184,7 +186,7 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
||||
pkb_push ( pkb, ll_protocol->ll_header_len );
|
||||
ll_protocol->fill_llh ( &llhdr, pkb );
|
||||
|
||||
/* Transmit packet */
|
||||
/* Hand off packet to network device */
|
||||
if ( ( rc = netdev->transmit ( netdev, pkb ) ) != 0 ) {
|
||||
DBG ( "Device failed to transmit packet\n" );
|
||||
return rc;
|
||||
@ -200,9 +202,8 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
||||
* @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.
|
||||
* Transmits the packet via the appropriate network device. This
|
||||
* function takes ownership of the packet buffer.
|
||||
*/
|
||||
int net_transmit ( struct pk_buff *pkb ) {
|
||||
return net_transmit_via ( pkb, NULL );
|
||||
@ -244,41 +245,83 @@ struct pk_buff * net_rx_dequeue ( void ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void net_run ( void ) {
|
||||
struct pk_buff *pkb;
|
||||
/**
|
||||
* Process received packet
|
||||
*
|
||||
* @v pkb Packet buffer
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* Processes a packet received from the network (and, usually, removed
|
||||
* from the RX queue by net_rx_dequeue()). This call takes ownership
|
||||
* of the packet buffer.
|
||||
*/
|
||||
int net_rx_process ( struct pk_buff *pkb ) {
|
||||
struct ll_protocol *ll_protocol;
|
||||
struct ll_header llhdr;
|
||||
struct net_protocol *net_protocol;
|
||||
int rc;
|
||||
|
||||
while ( ( pkb = net_rx_dequeue () ) ) {
|
||||
|
||||
/* Parse link-layer header */
|
||||
ll_protocol = pkb->ll_protocol;
|
||||
ll_protocol->parse_llh ( pkb, &llhdr );
|
||||
|
||||
/* Identify network-layer protocol */
|
||||
net_protocol = find_net_protocol ( llhdr.net_proto );
|
||||
if ( ! net_protocol ) {
|
||||
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" );
|
||||
/* Parse link-layer header */
|
||||
ll_protocol = pkb->ll_protocol;
|
||||
ll_protocol->parse_llh ( pkb, &llhdr );
|
||||
|
||||
/* Identify network-layer protocol */
|
||||
net_protocol = find_net_protocol ( llhdr.net_proto );
|
||||
if ( ! net_protocol ) {
|
||||
DBG ( "Unknown network-layer protocol %x\n",
|
||||
ntohs ( llhdr.net_proto ) );
|
||||
free_pkb ( pkb );
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
pkb->net_protocol = net_protocol;
|
||||
|
||||
/* Strip off link-layer header */
|
||||
pkb_pull ( pkb, ll_protocol->ll_header_len );
|
||||
|
||||
/* Hand off to network layer */
|
||||
if ( ( rc = net_protocol->rx_process ( pkb ) ) != 0 ) {
|
||||
DBG ( "Network-layer protocol dropped packet\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Single-step the network stack
|
||||
*
|
||||
* @v process Network stack process
|
||||
*
|
||||
* This polls all interfaces for any received packets, and processes
|
||||
* any packets that are received during this poll.
|
||||
*/
|
||||
static void net_step ( struct process *process ) {
|
||||
struct pk_buff *pkb;
|
||||
|
||||
/* Poll for new packets */
|
||||
net_poll();
|
||||
|
||||
/* Handle any received packets */
|
||||
while ( ( pkb = net_rx_dequeue () ) ) {
|
||||
net_rx_process ( pkb );
|
||||
DBG ( "Processed received packet\n" );
|
||||
}
|
||||
|
||||
/* Re-schedule ourself */
|
||||
schedule ( process );
|
||||
}
|
||||
|
||||
/** Networking stack process */
|
||||
static struct process net_process = {
|
||||
.step = net_step,
|
||||
};
|
||||
|
||||
static void init_net ( void ) {
|
||||
schedule ( &net_process );
|
||||
}
|
||||
|
||||
#include <init.h>
|
||||
|
||||
INIT_FN ( INIT_RPC, init_net, NULL, NULL );
|
||||
|
Loading…
Reference in New Issue
Block a user