From: Guo-Fu Tseng <coolda...@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 <coolda...@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 _______________________________________________ gPXE-devel mailing list gPXE-devel@etherboot.org http://etherboot.org/mailman/listinfo/gpxe-devel