Ksched interface cleanup, smp_idle() cleanup
[akaros.git] / kern / src / net.c
1 /* Copyright (c) 2010 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Arch independent networking infrastructure */
6
7 /* Computes an IP checksum over buf.  The checksum is the one's-comp of the
8  * one's complement 16 bit sum of the payload.  Anything above 16 bits gets
9  * added back to the lower 16 bits, which is what the mask and add is doing.
10  * Check out http://www.netfor2.com/checksum.html for more info.
11  *
12  * If you want to start with a sum from something else (like the UDP
13  * pseudo-header), pass it in as init_sum. */
14
15 #include <net.h>
16 #include <stdio.h>
17
18 uint16_t __ip_checksum(void *buf, unsigned int len, uint32_t sum)
19 {
20         /* Knock out 2 bytes at a time */
21         while (len > 1) {
22                 /* Careful of endianness.  The packet is in network ordering */
23                 sum += ntohs(*((uint16_t*)buf));
24                 buf += sizeof(uint16_t);
25                 /* In case we get close to overflowing while summing. */
26                 if (sum & 0x80000000)
27                         sum = (sum & 0xFFFF) + (sum >> 16);
28                 len -= 2;
29         }
30         /* Handle the last byte, if any */
31         if (len)
32                 sum += *(uint8_t*)buf;
33         /* Add the top 16 bytes to the lower ones, til it is done */
34         while (sum >> 16)
35                 sum = (sum & 0xFFFF) + (sum >> 16);
36         return ~sum;
37 }
38
39 /* Computes the checksum for the IP header.  We could write it in, but for now
40  * we'll return the checksum (in host-ordering) and have the caller store the
41  * value.  The retval is in host ordering. */
42 uint16_t ip_checksum(struct ip_hdr *ip_hdr)
43 {
44         unsigned int ip_hdr_len = ip_hdr->hdr_len * sizeof(uint32_t);
45         ip_hdr->checksum = 0;
46         return __ip_checksum(ip_hdr, ip_hdr_len, 0);
47 }
48
49 /* Computes the checksum for the UDP header.  We could write it in, but for now
50  * we'll return the checksum (in host-ordering) and have the caller store the
51  * value.  Note that the UDP header needs info from the IP header (strictly
52  * speaking, just the src and destination IPs).  */
53 uint16_t udp_checksum(struct ip_hdr *ip_hdr, struct udp_hdr *udp_hdr)
54 {
55         /* Add up the info for the UDP pseudo-header */
56         uint32_t udp_pseudosum = 0;
57         uint16_t udp_len = ntohs(udp_hdr->length);
58         udp_hdr->checksum = 0;
59         udp_pseudosum += ntohs(ip_hdr->src_addr & 0xffff);
60         udp_pseudosum += ntohs(ip_hdr->src_addr >> 16);
61         udp_pseudosum += ntohs(ip_hdr->dst_addr & 0xffff);
62         udp_pseudosum += ntohs(ip_hdr->dst_addr >> 16);
63         udp_pseudosum += ip_hdr->protocol;
64         udp_pseudosum += udp_len;
65         return __ip_checksum(udp_hdr, udp_len, udp_pseudosum);
66 }
67 /* Print out a network packet in the same format as tcpdump, making it easier 
68  * to compare */
69 void dumppacket(unsigned char *buff, size_t len)
70 {
71         int i;
72         for (i=0; i<len; i++) {
73                 if (i%16 == 0)
74                         printk("0x%x\t", i/16);
75                 printk("%02x", buff[i]);
76                 if (i%2 != 0)
77                         printk(" ");
78                 if ((i+1)%16 == 0)
79                         printk("\n");
80         }
81 }