[gPXE-devel] [PATCH 1/2] [net] Adding RX packet checksum offload support
Guo-Fu Tseng
cooldavid at cooldavid.org
Fri Jul 30 09:02:18 EDT 2010
From: Guo-Fu Tseng <cooldavid at cooldavid.org>
Add a field in struct io_buffer to pass checksum status from hardware.
If the hardware dose not support just ignore this field, it'll work as
usual.
I see that net/ipv6 does not check for checksum, so I temporary ignored
it.
Signed-off-by: Guo-Fu Tseng <cooldavid at cooldavid.org>
---
src/core/iobuf.c | 1 +
src/include/gpxe/iobuf.h | 13 +++++++++++++
src/net/ipv4.c | 8 +++++---
src/net/tcp.c | 18 ++++++++++--------
src/net/udp.c | 2 +-
5 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/src/core/iobuf.c b/src/core/iobuf.c
index 1ce7890..731a3c7 100644
--- a/src/core/iobuf.c
+++ b/src/core/iobuf.c
@@ -58,6 +58,7 @@ struct io_buffer * alloc_iob ( size_t len ) {
iobuf = ( struct io_buffer * ) ( data + len );
iobuf->head = iobuf->data = iobuf->tail = data;
iobuf->end = iobuf;
+ iobuf->csum_stat = 0;
return iobuf;
}
diff --git a/src/include/gpxe/iobuf.h b/src/include/gpxe/iobuf.h
index 8f05f9e..423500b 100644
--- a/src/include/gpxe/iobuf.h
+++ b/src/include/gpxe/iobuf.h
@@ -34,6 +34,16 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define IOB_ZLEN 64
/**
+ * Checksum Offloading Status
+ *
+ * Checksum status definitions. Currently only used for RX path.
+ */
+#define CHECKSUM_NONE 0
+#define CHECKSUM_UNNECESSARY 1
+#define CHECKSUM_COMPLETE 2
+#define CHECKSUM_PARTIAL 3
+
+/**
* A persistent I/O buffer
*
* This data structure encapsulates a long-lived I/O buffer. The
@@ -57,6 +67,9 @@ struct io_buffer {
void *tail;
/** End of the buffer */
void *end;
+
+ /** Checksum Offloading Status **/
+ uint32_t csum_stat;
};
/**
diff --git a/src/net/ipv4.c b/src/net/ipv4.c
index 92d0684..f065ca6 100644
--- a/src/net/ipv4.c
+++ b/src/net/ipv4.c
@@ -390,7 +390,7 @@ static int ipv4_rx ( struct io_buffer *iobuf, struct net_device *netdev __unused
struct sockaddr_tcpip st;
} src, dest;
uint16_t csum;
- uint16_t pshdr_csum;
+ uint16_t pshdr_csum = 0;
int rc;
/* Sanity check the IPv4 header */
@@ -414,7 +414,8 @@ static int ipv4_rx ( struct io_buffer *iobuf, struct net_device *netdev __unused
"(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
goto err;
}
- if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
+ if ( ( iobuf->csum_stat != CHECKSUM_COMPLETE ) &&
+ ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
DBG ( "IPv4 checksum incorrect (is %04x including checksum "
"field, should be 0000)\n", csum );
goto err;
@@ -441,7 +442,8 @@ static int ipv4_rx ( struct io_buffer *iobuf, struct net_device *netdev __unused
* checksum and then strip off the IPv4 header.
*/
iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) );
- pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
+ if ( iobuf->csum_stat != CHECKSUM_COMPLETE )
+ pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
iob_pull ( iobuf, hdrlen );
/* Fragment reassembly */
diff --git a/src/net/tcp.c b/src/net/tcp.c
index f9fd409..6a7b340 100644
--- a/src/net/tcp.c
+++ b/src/net/tcp.c
@@ -924,15 +924,17 @@ static int tcp_rx ( struct io_buffer *iobuf,
rc = -EINVAL;
goto discard;
}
- csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data,
- iob_len ( iobuf ) );
- if ( csum != 0 ) {
- DBG ( "TCP checksum incorrect (is %04x including checksum "
- "field, should be 0000)\n", csum );
- rc = -EINVAL;
- goto discard;
+ if ( iobuf->csum_stat != CHECKSUM_COMPLETE ) {
+ csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data,
+ iob_len ( iobuf ) );
+ if ( csum != 0 ) {
+ DBG ( "TCP checksum incorrect (is %04x including checksum "
+ "field, should be 0000)\n", csum );
+ rc = -EINVAL;
+ goto discard;
+ }
}
-
+
/* Parse parameters from header and strip header */
tcp = tcp_demux ( tcphdr->dest );
start_seq = seq = ntohl ( tcphdr->seq );
diff --git a/src/net/udp.c b/src/net/udp.c
index 1441d53..26c4c28 100644
--- a/src/net/udp.c
+++ b/src/net/udp.c
@@ -298,7 +298,7 @@ static int udp_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
rc = -EINVAL;
goto done;
}
- if ( udphdr->chksum ) {
+ if ( udphdr->chksum && ( iobuf->csum_stat != CHECKSUM_COMPLETE ) ) {
csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data, ulen );
if ( csum != 0 ) {
DBG ( "UDP checksum incorrect (is %04x including "
--
1.7.1
More information about the gPXE-devel
mailing list