e76d8e3c099b39cdb13cc38c03ba4239d49a46f7
[barrelfish] / lib / devif / backends / net / ip / devif_backend_ip.c
1 /*
2  * Copyright (c) 2017, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Universit√§tstrasse 4, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <stdbool.h>
13 #include <barrelfish/barrelfish.h>
14 #include <barrelfish/waitset.h>
15 #include <barrelfish/deferred.h>
16 #include <devif/queue_interface.h>
17 #include <devif/backends/net/ip.h>
18 #include <lwip/inet_chksum.h>
19 #include <lwip/lwip/inet.h>
20 #include <net_interfaces/flags.h>
21 #include <net/net.h>
22 #include <net/net_queue.h>
23 #include <net/net_filter.h>
24 #include <net/dhcp.h>
25 #include "../../../queue_interface_internal.h"
26 #include "../headers.h"
27
28 #define MAX_NUM_REGIONS 64
29
30 //#define DEBUG_ENABLED
31
32 #if defined(DEBUG_ENABLED) 
33 #define DEBUG(x...) do { printf("IP_QUEUE: %s.%d:%s:%d: ", \
34             disp_name(), disp_get_core_id(), __func__, __LINE__); \
35                 printf(x);\
36         } while (0)
37
38 #else
39 #define DEBUG(x...) ((void)0)
40 #endif 
41
42 struct region_vaddr {
43     void* va;
44     regionid_t rid;
45 };
46
47 struct pkt_ip_headers {
48     struct eth_hdr eth;
49     struct ip_hdr ip;
50 } __attribute__ ((packed));
51
52 struct ip_q {
53     struct devq my_q;
54     struct devq* q;
55     struct pkt_ip_headers header; // can fill in this header and reuse it by copying
56     struct region_vaddr regions[MAX_NUM_REGIONS];
57     struct net_filter_state* filter;
58     uint16_t hdr_len;
59 };
60
61
62 #ifdef DEBUG_ENABLED
63 static void print_buffer(struct ip_q* q, void* start, uint64_t len)
64 {
65     uint8_t* buf = (uint8_t*) start;
66     printf("Packet in region at address %p len %zu \n",
67            buf, len);
68     for (int i = 0; i < len; i+=2) {
69         if (((i % 16) == 0) && i > 0) {
70             printf("\n");
71         }
72         printf("%2X", buf[i]);
73         printf("%2X ", buf[i+1]);
74     }
75     printf("\n");
76 }
77 #endif
78
79 static errval_t ip_register(struct devq* q, struct capref cap,
80                             regionid_t rid) 
81 {
82        
83     errval_t err;
84     struct frame_identity frameid = { .base = 0, .bytes = 0 };
85
86     struct ip_q* que = (struct ip_q*) q;
87
88     // Map device registers
89     invoke_frame_identify(cap, &frameid);
90
91     err = vspace_map_one_frame_attr(&que->regions[rid % MAX_NUM_REGIONS].va, 
92                                     frameid.bytes, cap, VREGION_FLAGS_READ_WRITE, 
93                                     NULL, NULL);
94     if (err_is_fail(err)) {
95         DEBUG_ERR(err, "vspace_map_one_frame failed");
96         return err;
97     }
98     que->regions[rid % MAX_NUM_REGIONS].rid = rid;
99     DEBUG("id-%d va-%p \n", que->regions[rid % MAX_NUM_REGIONS].rid, 
100           que->regions[rid % MAX_NUM_REGIONS].va);
101
102     return que->q->f.reg(que->q, cap, rid);
103 }
104
105 static errval_t ip_deregister(struct devq* q, regionid_t rid) 
106 {
107     
108     struct ip_q* que = (struct ip_q*) q;
109     que->regions[rid % MAX_NUM_REGIONS].va = NULL;
110     que->regions[rid % MAX_NUM_REGIONS].rid = 0;
111     return que->q->f.dereg(que->q, rid);
112 }
113
114
115 static errval_t ip_control(struct devq* q, uint64_t cmd, uint64_t value,
116                            uint64_t* result)
117 {
118     struct ip_q* que = (struct ip_q*) q;
119     return que->q->f.ctrl(que->q, cmd, value, result);
120 }
121
122
123 static errval_t ip_notify(struct devq* q)
124 {
125     struct ip_q* que = (struct ip_q*) q;
126     return que->q->f.notify(que->q);
127 }
128
129 static errval_t ip_enqueue(struct devq* q, regionid_t rid, 
130                            genoffset_t offset, genoffset_t length,
131                            genoffset_t valid_data, genoffset_t valid_length,
132                            uint64_t flags)
133 {
134
135     // for now limit length
136     //  TODO fragmentation
137
138     struct ip_q* que = (struct ip_q*) q;
139     if (flags & NETIF_TXFLAG) {
140         
141         DEBUG("TX rid: %d offset %ld length %ld valid_length %ld \n", rid, offset, 
142               length, valid_length);
143         assert(valid_length <= 1500);    
144         que->header.ip._len = htons(valid_length + IP_HLEN);   
145         que->header.ip._chksum = inet_chksum(&que->header, IP_HLEN);
146
147         assert(que->regions[rid % MAX_NUM_REGIONS].va != NULL);
148
149         uint8_t* start = (uint8_t*) que->regions[rid % MAX_NUM_REGIONS].va + 
150                          offset + valid_data;   
151
152         memcpy(start, &que->header, sizeof(que->header));   
153
154         return que->q->f.enq(que->q, rid, offset, length, valid_data, 
155                              valid_length+sizeof(struct pkt_ip_headers), flags);
156     } 
157
158     if (flags & NETIF_RXFLAG) {
159         assert(valid_length <= 2048);    
160         DEBUG("RX rid: %d offset %ld length %ld valid_length %ld \n", rid, offset, 
161               length, valid_length);
162         return que->q->f.enq(que->q, rid, offset, length, valid_data, 
163                              valid_length, flags);
164     } 
165
166     return NET_QUEUE_ERR_UNKNOWN_BUF_TYPE;
167 }
168
169 static errval_t ip_dequeue(struct devq* q, regionid_t* rid, genoffset_t* offset,
170                            genoffset_t* length, genoffset_t* valid_data,
171                            genoffset_t* valid_length, uint64_t* flags)
172 {
173     errval_t err;
174     struct ip_q* que = (struct ip_q*) q;
175
176     err = que->q->f.deq(que->q, rid, offset, length, valid_data, valid_length, flags);
177     if (err_is_fail(err)) {  
178         return err;
179     }
180
181     if (*flags & NETIF_RXFLAG) {
182         DEBUG("RX rid: %d offset %ld valid_data %ld length %ld va %p \n", *rid, 
183               *offset, *valid_data, 
184               *valid_length, que->regions[*rid % MAX_NUM_REGIONS].va + *offset + *valid_data);
185
186         struct pkt_ip_headers* header = (struct pkt_ip_headers*) 
187                                          (que->regions[*rid % MAX_NUM_REGIONS].va +
188                                          *offset + *valid_data);
189  
190         // IP checksum
191         if (header->ip._chksum == inet_chksum(&header->ip, IP_HLEN)) {
192             printf("IP queue: dropping packet wrong checksum \n");
193             err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
194             return err_push(err, NET_QUEUE_ERR_CHECKSUM);
195         }
196
197         // Correct ip for this queue?
198         if (header->ip.src != que->header.ip.dest) {
199             printf("IP queue: dropping packet, wrong IP is %"PRIu32" should be %"PRIu32"\n",
200                    header->ip.src, que->header.ip.dest);
201             err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
202             return err_push(err, NET_QUEUE_ERR_WRONG_IP);
203         }
204         
205 #ifdef DEBUG_ENABLED
206         print_buffer(que, que->regions[*rid % MAX_NUM_REGIONS].va + *offset, *valid_length);
207 #endif
208
209         *valid_data = IP_HLEN + ETH_HLEN;
210         *valid_length = ntohs(header->ip._len) - IP_HLEN;
211         //print_buffer(que, que->regions[*rid % MAX_NUM_REGIONS].va + *offset+ *valid_data, *valid_length);
212         return SYS_ERR_OK;
213     }
214
215 #ifdef DEBUG_ENABLED
216     DEBUG("TX rid: %d offset %ld length %ld \n", *rid, *offset, 
217           *valid_length);
218 #endif
219
220     return SYS_ERR_OK;
221 }
222
223 /*
224  * Public functions
225  *
226  */
227 errval_t ip_create(struct ip_q** q, const char* card_name, uint64_t* qid,
228                    uint8_t prot, uint32_t dst_ip,
229                    struct eth_addr dst_mac, inthandler_t interrupt, bool poll)
230 {
231     errval_t err;
232     struct ip_q* que;
233     que = calloc(1, sizeof(struct ip_q));
234     assert(que);
235
236     // init other queue
237     err = net_queue_create(interrupt, card_name, qid, poll, &que->q);
238     if (err_is_fail(err)) {
239         return err;
240     }
241
242     err = devq_init(&que->my_q, false);
243     if (err_is_fail(err)) {
244         // TODO net queue destroy
245         return err;
246     }   
247
248     uint64_t src_mac;
249     err = devq_control(que->q, 0, 0, &src_mac);
250     if (err_is_fail(err)) {
251         return err;
252     }
253    
254     uint32_t src_ip;
255     err = net_config_current_ip_query(NET_FLAGS_BLOCKING_INIT, &src_ip);
256     if (err_is_fail(err)) {
257         return err;
258     }
259
260     // fill in header that is reused for each packet
261     // Ethernet
262     memcpy(&(que->header.eth.dest.addr), &dst_mac, ETH_HWADDR_LEN);
263     memcpy(&(que->header.eth.src.addr), &src_mac, ETH_HWADDR_LEN);
264     que->header.eth.type = htons(ETHTYPE_IP);
265
266     // IP
267     que->header.ip._v_hl = 69;
268     IPH_TOS_SET(&que->header.ip, 0x0);
269     IPH_ID_SET(&que->header.ip, htons(0x3));
270     que->header.ip._offset = htons(IP_DF);
271     que->header.ip._proto = 0x11; // IP
272     que->header.ip._ttl = 0x40; // 64
273     que->header.ip.src = src_ip;
274     que->header.ip.dest = htonl(dst_ip);
275
276     que->my_q.f.reg = ip_register;
277     que->my_q.f.dereg = ip_deregister;
278     que->my_q.f.ctrl = ip_control;
279     que->my_q.f.notify = ip_notify;
280     que->my_q.f.enq = ip_enqueue;
281     que->my_q.f.deq = ip_dequeue;
282     *q = que;
283
284     /*
285     switch(prot) {
286         case UDP_PROT:
287             que->hdr_len = IP_HLEN + sizeof(struct udp_hdr);
288             break;
289         case TCP_PROT:
290             // TODO
291             break;
292         default:
293             USER_PANIC("Unkown protocol specified when creating IP queue \n");
294
295     }
296     */
297
298     return SYS_ERR_OK;
299 }
300
301 errval_t ip_destroy(struct ip_q* q)
302 {
303     // TODO destroy q->q;
304     free(q);    
305
306     return SYS_ERR_OK;
307 }
308
309
310