Socket infrastructure change and basic udp send.
[akaros.git] / kern / src / net / ip.c
1 #include <ros/common.h>
2 #include <assert.h>
3 #include <socket.h>
4 #include <bits/netinet.h>
5 #include <net.h>
6 #include <net/ip.h>
7 #include <net/udp.h>
8 #include <ros/errno.h>
9 #include <arch/nic_common.h>
10
11 /* statically configured next gateway */
12 const uint8_t GTWAY[6] = {0xda, 0x76, 0xe7, 0x4c, 0xca, 0x7e};
13
14 /* TODO: ip id unique for all ip packets? or is it unique for a flow? */
15 // can do atomic increment at a minimum
16 static uint16_t ip_id = 0;
17 struct in_addr global_ip = {IP_ADDR};
18
19 /* TODO: build arp table, and look up */
20 int eth_send(struct pbuf *p, struct in_addr *dest) {
21         uint32_t bytes_sent; 
22         if (pbuf_header(p, sizeof(struct ethernet_hdr)) != 0){
23                 warn("eth_send buffer ran out");
24                 /* unsuccessful, needs to allocate */   
25                 return -ENOBUFS;
26         }
27
28         struct ethernet_hdr *ethhdr = (struct ethernet_hdr *)p->payload; 
29         // TODO: for now just forward to gateway
30         memcpy(ethhdr->dst_mac, GTWAY, 6);
31         memcpy(ethhdr->src_mac, device_mac, 6);
32         ethhdr->eth_type = htons(IP_ETH_TYPE);
33         /* The reason for not sending to send_nic for each pbuf in the chain
34          * is so that we can send from multi-buffer later.
35          */
36         if (send_pbuf){
37         #if ETH_PAD_SIZE
38                 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
39         #endif
40                 bytes_sent = send_pbuf(p);
41                 pbuf_header(p, ETH_PAD_SIZE); /* when do we deallocate p? */
42                 return bytes_sent;
43         }
44         else {
45                 warn("no pbuf send function \n");
46                 return -1;
47         }
48         /* is the address local , if no, search for MAC of the gateway and dest to gateway */
49         /* if address is local, use arp etc */
50
51 }
52
53 /* while it would be nice to write a generic send_pbuf it is impossible to do so in
54  * efficiently.
55  */
56 /* Assume no ip options */
57 int ip_output(struct pbuf *p, struct in_addr *src, struct in_addr *dest, uint8_t proto) {
58         struct pbuf *q;
59         struct ip_hdr *iphdr;   
60         /* TODO: Check for IP_HDRINCL */
61         if (dest->s_addr == IP_HDRINCL) {
62                 /*send right away since */
63                 warn("header included in the ip packets");
64                 return -1;
65         }
66         if (pbuf_header(p, IP_HDR_SZ)) {
67                 warn("buffer ran out");
68                 /* unsuccessful, needs to allocate */   
69                 return -ENOBUFS;
70         }
71         iphdr = (struct ip_hdr *) p->payload;
72
73         /* successful */
74         iphdr->version = IPPROTO_IPV4;
75         /* assume no IP options */
76         iphdr->hdr_len = IP_HDR_SZ >> 2;
77         iphdr->tos = 0;
78         iphdr->packet_len = htons(p->tot_len);
79         // TODO: NET_LOCK
80         iphdr->id = htons (ip_id); // 1
81         ip_id++;
82         iphdr->flags_frags = htons(0); // 4000  may fragment
83         iphdr->protocol = proto;
84         iphdr->ttl = htons(DEFAULT_TTL);
85         /* Eventually if we support more than one device this may change */
86         printk("src ip %x, dest ip %x \n", src->s_addr, dest->s_addr);
87         iphdr->src_addr = htonl(src->s_addr);
88         iphdr->dst_addr = (dest->s_addr);
89         /* force hardware checksum
90          * TODO: provide option to do both hardware/software checksum
91          */
92         /* Since the IP header is set already, we can compute the checksum. */
93         /* TODO: Use the card to calculate the checksum */
94         iphdr->checksum = htons(ip_checksum(iphdr)); //7ab6
95         if (p->tot_len > DEFAULT_MTU) /*MAX MTU? header included */
96                 return -1;//ip_frag(p, dest);
97         else
98                 return eth_send(p, dest);
99 }
100
101