devif: added dst MAC lookup to UDP queue init
[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 <net/arp.h>
26 #include "../../../queue_interface_internal.h"
27 #include "../headers.h"
28
29 #define MAX_NUM_REGIONS 64
30
31 //#define DEBUG_ENABLED
32
33 #if defined(DEBUG_ENABLED) 
34 #define DEBUG(x...) do { printf("IP_QUEUE: %s.%d:%s:%d: ", \
35             disp_name(), disp_get_core_id(), __func__, __LINE__); \
36                 printf(x);\
37         } while (0)
38
39 #else
40 #define DEBUG(x...) ((void)0)
41 #endif 
42
43 struct region_vaddr {
44     void* va;
45     regionid_t rid;
46 };
47
48 struct pkt_ip_headers {
49     struct eth_hdr eth;
50     struct ip_hdr ip;
51 } __attribute__ ((packed));
52
53 struct ip_q {
54     struct devq my_q;
55     struct devq* q;
56     struct pkt_ip_headers header; // can fill in this header and reuse it by copying
57     struct region_vaddr regions[MAX_NUM_REGIONS];
58     struct net_filter_state* filter;
59     uint16_t hdr_len;
60 };
61
62
63 #ifdef DEBUG_ENABLED
64 static void print_buffer(struct ip_q* q, void* start, uint64_t len)
65 {
66     uint8_t* buf = (uint8_t*) start;
67     printf("Packet in region at address %p len %zu \n",
68            buf, len);
69     for (int i = 0; i < len; i+=2) {
70         if (((i % 16) == 0) && i > 0) {
71             printf("\n");
72         }
73         printf("%2X", buf[i]);
74         printf("%2X ", buf[i+1]);
75     }
76     printf("\n");
77 }
78 #endif
79
80 static errval_t ip_register(struct devq* q, struct capref cap,
81                             regionid_t rid) 
82 {
83        
84     errval_t err;
85     struct frame_identity frameid = { .base = 0, .bytes = 0 };
86
87     struct ip_q* que = (struct ip_q*) q;
88
89     // Map device registers
90     invoke_frame_identify(cap, &frameid);
91
92     err = vspace_map_one_frame_attr(&que->regions[rid % MAX_NUM_REGIONS].va, 
93                                     frameid.bytes, cap, VREGION_FLAGS_READ_WRITE, 
94                                     NULL, NULL);
95     if (err_is_fail(err)) {
96         DEBUG_ERR(err, "vspace_map_one_frame failed");
97         return err;
98     }
99     que->regions[rid % MAX_NUM_REGIONS].rid = rid;
100     DEBUG("id-%d va-%p \n", que->regions[rid % MAX_NUM_REGIONS].rid, 
101           que->regions[rid % MAX_NUM_REGIONS].va);
102
103     return que->q->f.reg(que->q, cap, rid);
104 }
105
106 static errval_t ip_deregister(struct devq* q, regionid_t rid) 
107 {
108     
109     struct ip_q* que = (struct ip_q*) q;
110     que->regions[rid % MAX_NUM_REGIONS].va = NULL;
111     que->regions[rid % MAX_NUM_REGIONS].rid = 0;
112     return que->q->f.dereg(que->q, rid);
113 }
114
115
116 static errval_t ip_control(struct devq* q, uint64_t cmd, uint64_t value,
117                            uint64_t* result)
118 {
119     struct ip_q* que = (struct ip_q*) q;
120     return que->q->f.ctrl(que->q, cmd, value, result);
121 }
122
123
124 static errval_t ip_notify(struct devq* q)
125 {
126     struct ip_q* que = (struct ip_q*) q;
127     return que->q->f.notify(que->q);
128 }
129
130 static errval_t ip_enqueue(struct devq* q, regionid_t rid, 
131                            genoffset_t offset, genoffset_t length,
132                            genoffset_t valid_data, genoffset_t valid_length,
133                            uint64_t flags)
134 {
135
136     // for now limit length
137     //  TODO fragmentation
138
139     struct ip_q* que = (struct ip_q*) q;
140     if (flags & NETIF_TXFLAG) {
141         
142         DEBUG("TX rid: %d offset %ld length %ld valid_length %ld \n", rid, offset, 
143               length, valid_length);
144         assert(valid_length <= 1500);    
145         que->header.ip._len = htons(valid_length + IP_HLEN);   
146         que->header.ip._chksum = inet_chksum(&que->header, IP_HLEN);
147
148         assert(que->regions[rid % MAX_NUM_REGIONS].va != NULL);
149
150         uint8_t* start = (uint8_t*) que->regions[rid % MAX_NUM_REGIONS].va + 
151                          offset + valid_data;   
152
153         memcpy(start, &que->header, sizeof(que->header));   
154
155         return que->q->f.enq(que->q, rid, offset, length, valid_data, 
156                              valid_length+sizeof(struct pkt_ip_headers), flags);
157     } 
158
159     if (flags & NETIF_RXFLAG) {
160         assert(valid_length <= 2048);    
161         DEBUG("RX rid: %d offset %ld length %ld valid_length %ld \n", rid, offset, 
162               length, valid_length);
163         return que->q->f.enq(que->q, rid, offset, length, valid_data, 
164                              valid_length, flags);
165     } 
166
167     return NET_QUEUE_ERR_UNKNOWN_BUF_TYPE;
168 }
169
170 static errval_t ip_dequeue(struct devq* q, regionid_t* rid, genoffset_t* offset,
171                            genoffset_t* length, genoffset_t* valid_data,
172                            genoffset_t* valid_length, uint64_t* flags)
173 {
174     errval_t err;
175     struct ip_q* que = (struct ip_q*) q;
176
177     err = que->q->f.deq(que->q, rid, offset, length, valid_data, valid_length, flags);
178     if (err_is_fail(err)) {  
179         return err;
180     }
181
182     if (*flags & NETIF_RXFLAG) {
183         DEBUG("RX rid: %d offset %ld valid_data %ld length %ld va %p \n", *rid, 
184               *offset, *valid_data, 
185               *valid_length, que->regions[*rid % MAX_NUM_REGIONS].va + *offset + *valid_data);
186
187         struct pkt_ip_headers* header = (struct pkt_ip_headers*) 
188                                          (que->regions[*rid % MAX_NUM_REGIONS].va +
189                                          *offset + *valid_data);
190  
191         // IP checksum
192         if (header->ip._chksum == inet_chksum(&header->ip, IP_HLEN)) {
193             printf("IP queue: dropping packet wrong checksum \n");
194             err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
195             return err_push(err, NET_QUEUE_ERR_CHECKSUM);
196         }
197
198         // Correct ip for this queue?
199         if (header->ip.src != que->header.ip.dest) {
200             printf("IP queue: dropping packet, wrong IP is %"PRIu32" should be %"PRIu32"\n",
201                    header->ip.src, que->header.ip.dest);
202             err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
203             return err_push(err, NET_QUEUE_ERR_WRONG_IP);
204         }
205         
206 #ifdef DEBUG_ENABLED
207         print_buffer(que, que->regions[*rid % MAX_NUM_REGIONS].va + *offset, *valid_length);
208 #endif
209
210         *valid_data = IP_HLEN + ETH_HLEN;
211         *valid_length = ntohs(header->ip._len) - IP_HLEN;
212         //print_buffer(que, que->regions[*rid % MAX_NUM_REGIONS].va + *offset+ *valid_data, *valid_length);
213         return SYS_ERR_OK;
214     }
215
216 #ifdef DEBUG_ENABLED
217     DEBUG("TX rid: %d offset %ld length %ld \n", *rid, *offset, 
218           *valid_length);
219 #endif
220
221     return SYS_ERR_OK;
222 }
223
224 /*
225  * Public functions
226  *
227  */
228 errval_t ip_create(struct ip_q** q, const char* card_name, uint64_t* qid,
229                    uint8_t prot, uint32_t dst_ip, 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     uint64_t mac;
261     err = arp_service_get_mac(htonl(dst_ip), &mac);
262     if (err_is_fail(err)) {
263         return err;
264     }
265
266     // fill in header that is reused for each packet
267     // Ethernet
268     memcpy(&(que->header.eth.dest.addr), &mac, ETH_HWADDR_LEN);
269     memcpy(&(que->header.eth.src.addr), &src_mac, ETH_HWADDR_LEN);
270     que->header.eth.type = htons(ETHTYPE_IP);
271
272     // IP
273     que->header.ip._v_hl = 69;
274     IPH_TOS_SET(&que->header.ip, 0x0);
275     IPH_ID_SET(&que->header.ip, htons(0x3));
276     que->header.ip._offset = htons(IP_DF);
277     que->header.ip._proto = 0x11; // IP
278     que->header.ip._ttl = 0x40; // 64
279     que->header.ip.src = src_ip;
280     que->header.ip.dest = htonl(dst_ip);
281
282     que->my_q.f.reg = ip_register;
283     que->my_q.f.dereg = ip_deregister;
284     que->my_q.f.ctrl = ip_control;
285     que->my_q.f.notify = ip_notify;
286     que->my_q.f.enq = ip_enqueue;
287     que->my_q.f.deq = ip_dequeue;
288     *q = que;
289
290     /*
291     switch(prot) {
292         case UDP_PROT:
293             que->hdr_len = IP_HLEN + sizeof(struct udp_hdr);
294             break;
295         case TCP_PROT:
296             // TODO
297             break;
298         default:
299             USER_PANIC("Unkown protocol specified when creating IP queue \n");
300
301     }
302     */
303
304     return SYS_ERR_OK;
305 }
306
307 errval_t ip_destroy(struct ip_q* q)
308 {
309     // TODO destroy q->q;
310     free(q);    
311
312     return SYS_ERR_OK;
313 }
314
315
316