Clarified packet ownership transfer between a few functions.
Added a large number of missing calls to free_pkb(). In the case of UDP, no received packets were ever freed, which lead to memory exhaustion remarkably quickly once pxelinux started up. In general, any function with _rx() in its name which accepts a pk_buff *must* either call free_pkb() or pass the pkb to another _rx() function (e.g. the next layer up the stack). Since the UDP (and TCP) layers don't pass packet buffers up to the higher-layer protocols (the "applications"), they must free the packet buffer after calling the application's newdata() method.
This commit is contained in:
+5
-3
@@ -19,6 +19,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <byteswap.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <vsprintf.h>
|
||||
#include <gpxe/if_arp.h>
|
||||
@@ -68,21 +69,22 @@ static int eth_tx ( struct pk_buff *pkb, struct net_device *netdev,
|
||||
* Strips off the Ethernet link-layer header and passes up to the
|
||||
* network-layer protocol.
|
||||
*/
|
||||
static void eth_rx ( struct pk_buff *pkb, struct net_device *netdev ) {
|
||||
static int eth_rx ( struct pk_buff *pkb, struct net_device *netdev ) {
|
||||
struct ethhdr *ethhdr = pkb->data;
|
||||
|
||||
/* Sanity check */
|
||||
if ( pkb_len ( pkb ) < sizeof ( *ethhdr ) ) {
|
||||
DBG ( "Ethernet packet too short (%d bytes)\n",
|
||||
pkb_len ( pkb ) );
|
||||
return;
|
||||
free_pkb ( pkb );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Strip off Ethernet header */
|
||||
pkb_pull ( pkb, sizeof ( *ethhdr ) );
|
||||
|
||||
/* Hand off to network-layer protocol */
|
||||
net_rx ( pkb, netdev, ethhdr->h_protocol, ethhdr->h_source );
|
||||
return net_rx ( pkb, netdev, ethhdr->h_protocol, ethhdr->h_source );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user