xref: /kvmtool/net/uip/csum.c (revision 0134a2a7e319c13a4d54689113d97b0fdebead7b)
1d8db9f85SAsias He #include "kvm/uip.h"
2d8db9f85SAsias He 
3d8db9f85SAsias He static u16 uip_csum(u16 csum, u8 *addr, u16 count)
4d8db9f85SAsias He {
5d8db9f85SAsias He 	long sum = csum;
6d8db9f85SAsias He 
7d8db9f85SAsias He 	while (count > 1) {
8d8db9f85SAsias He 		sum	+= *(u16 *)addr;
9d8db9f85SAsias He 		addr	+= 2;
10d8db9f85SAsias He 		count	-= 2;
11d8db9f85SAsias He 	}
12d8db9f85SAsias He 
13d8db9f85SAsias He 	if (count > 0)
14d8db9f85SAsias He 		sum += *(unsigned char *)addr;
15d8db9f85SAsias He 
16d8db9f85SAsias He 	while (sum>>16)
17d8db9f85SAsias He 		sum = (sum & 0xffff) + (sum >> 16);
18d8db9f85SAsias He 
19d8db9f85SAsias He 	return ~sum;
20d8db9f85SAsias He }
21d8db9f85SAsias He 
22d8db9f85SAsias He u16 uip_csum_ip(struct uip_ip *ip)
23d8db9f85SAsias He {
24d8db9f85SAsias He 	return uip_csum(0, &ip->vhl, uip_ip_hdrlen(ip));
25d8db9f85SAsias He }
26*0134a2a7SAsias He 
27*0134a2a7SAsias He u16 uip_csum_icmp(struct uip_icmp *icmp)
28*0134a2a7SAsias He {
29*0134a2a7SAsias He 	struct uip_ip *ip;
30*0134a2a7SAsias He 
31*0134a2a7SAsias He 	ip = &icmp->ip;
32*0134a2a7SAsias He 	return icmp->csum = uip_csum(0, &icmp->type, htons(ip->len) - uip_ip_hdrlen(ip) - 8); /* icmp header len = 8 */
33*0134a2a7SAsias He }
34