diff options
author | Michael Brown <mcb30@ipxe.org> | 2015-02-06 15:46:43 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2015-02-06 15:46:43 +0000 |
commit | 2e72d100af2d4f7720a64cb157c72e3fc714e4e2 (patch) | |
tree | 83042939338cee4f6d6fe23447d571e1245a0e9e /src/drivers/net | |
parent | 95bc563f0cdfb380b49b99d0e03f49d3739d3802 (diff) | |
download | ipxe-2e72d100af2d4f7720a64cb157c72e3fc714e4e2.tar.gz |
[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')
-rw-r--r-- | src/drivers/net/ncm.c | 12 |
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 ); |