From: Asias He Date: Wed, 29 Jun 2011 08:47:24 +0000 (+0800) Subject: kvm tools: Implement uip_csum_tcp() to calculate TCP checksum X-Git-Tag: next-20110824~3^2~168 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=68c44a69719bb50d971acd8b365d7d87e3ca6e3f;p=karo-tx-linux.git kvm tools: Implement uip_csum_tcp() to calculate TCP checksum Signed-off-by: Asias He Signed-off-by: Pekka Enberg --- diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h index 46cec2096d1a..37c87c697b26 100644 --- a/tools/kvm/include/kvm/uip.h +++ b/tools/kvm/include/kvm/uip.h @@ -28,8 +28,10 @@ /* * IP package maxium len == 64 KBytes * IP header == 20 Bytes + * TCP header == 20 Bytes * UDP header == 8 Bytes */ +#define UIP_MAX_TCP_PAYLOAD (64*1024 - 20 - 20 - 1) #define UIP_MAX_UDP_PAYLOAD (64*1024 - 20 - 8 - 1) struct uip_eth_addr { @@ -269,6 +271,7 @@ int uip_tx_do_arp(struct uip_tx_arg *arg); u16 uip_csum_icmp(struct uip_icmp *icmp); u16 uip_csum_udp(struct uip_udp *udp); +u16 uip_csum_tcp(struct uip_tcp *tcp); u16 uip_csum_ip(struct uip_ip *ip); struct uip_buf *uip_buf_set_used(struct uip_info *info, struct uip_buf *buf); diff --git a/tools/kvm/uip/csum.c b/tools/kvm/uip/csum.c index a152a0f85372..7ca8badaaeee 100644 --- a/tools/kvm/uip/csum.c +++ b/tools/kvm/uip/csum.c @@ -60,3 +60,33 @@ u16 uip_csum_udp(struct uip_udp *udp) } } + +u16 uip_csum_tcp(struct uip_tcp *tcp) +{ + struct uip_pseudo_hdr hdr; + struct uip_ip *ip; + u16 tcp_len; + u8 *pad; + + ip = &tcp->ip; + tcp_len = ntohs(ip->len) - uip_ip_hdrlen(ip); + + hdr.sip = ip->sip; + hdr.dip = ip->dip; + hdr.zero = 0; + hdr.proto = ip->proto; + hdr.len = htons(tcp_len); + + if (tcp_len > UIP_MAX_TCP_PAYLOAD + 20) + pr_warning("tcp_len(%d) is too large", tcp_len); + + if (tcp_len % 2) { + pad = (u8 *)&tcp->sport + tcp_len; + *pad = 0; + memcpy((u8 *)&tcp->sport + tcp_len + 1, &hdr, sizeof(hdr)); + return uip_csum(0, (u8 *)&tcp->sport, tcp_len + 1 + sizeof(hdr)); + } else { + memcpy((u8 *)&tcp->sport + tcp_len, &hdr, sizeof(hdr)); + return uip_csum(0, (u8 *)&tcp->sport, tcp_len + sizeof(hdr)); + } +}