summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/ncm.c
diff options
context:
space:
mode:
authorMichael Brown2015-02-06 16:46:43 +0100
committerMichael Brown2015-02-06 16:46:43 +0100
commit2e72d100af2d4f7720a64cb157c72e3fc714e4e2 (patch)
tree83042939338cee4f6d6fe23447d571e1245a0e9e /src/drivers/net/ncm.c
parent[pxe] Maintain a queue for received PXE UDP packets (diff)
downloadipxe-2e72d100af2d4f7720a64cb157c72e3fc714e4e2.tar.gz
ipxe-2e72d100af2d4f7720a64cb157c72e3fc714e4e2.tar.xz
ipxe-2e72d100af2d4f7720a64cb157c72e3fc714e4e2.zip
[ncm] Reserve headroom in received packets
Some protocols (such as ARP) may modify the received packet and re-use the same I/O buffer for transmission of a reply. To allow this, reserve sufficient headroom at the start of each received packet buffer for our transmit datapath headers. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/ncm.c')
-rw-r--r--src/drivers/net/ncm.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/drivers/net/ncm.c b/src/drivers/net/ncm.c
index 8a3f9388..0fc3ab79 100644
--- a/src/drivers/net/ncm.c
+++ b/src/drivers/net/ncm.c
@@ -390,6 +390,7 @@ static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
size_t ndp_len;
size_t pkt_offset;
size_t pkt_len;
+ size_t headroom;
size_t len;
/* Profile overall bulk IN completion */
@@ -460,13 +461,22 @@ static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
* while the device is running. We therefore copy the
* data to a new I/O buffer even if this is the only
* (or last) packet within the buffer.
+ *
+ * We reserve enough space at the start of each buffer
+ * to allow for our own transmission header, to
+ * support protocols such as ARP which may modify the
+ * received packet and reuse the same I/O buffer for
+ * transmission.
*/
- pkt = alloc_iob ( pkt_len );
+ headroom = ( sizeof ( struct ncm_ntb_header ) +
+ ncm->out.padding );
+ pkt = alloc_iob ( headroom + pkt_len );
if ( ! pkt ) {
/* Record error and continue */
netdev_rx_err ( netdev, NULL, -ENOMEM );
continue;
}
+ iob_reserve ( pkt, headroom );
memcpy ( iob_put ( pkt, pkt_len ),
( iobuf->data + pkt_offset ), pkt_len );