2 * Copyright (c) 2017, ETH Zurich.
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.
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>
22 #include <net/net_queue.h>
23 #include <net/net_filter.h>
25 #include "../../../queue_interface_internal.h"
26 #include "../headers.h"
28 #define MAX_NUM_REGIONS 64
30 //#define DEBUG_ENABLED
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__); \
39 #define DEBUG(x...) ((void)0)
47 struct pkt_ip_headers {
50 } __attribute__ ((packed));
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;
63 static void print_buffer(struct ip_q* q, void* start, uint64_t len)
65 uint8_t* buf = (uint8_t*) start;
66 printf("Packet in region at address %p len %zu \n",
68 for (int i = 0; i < len; i+=2) {
69 if (((i % 16) == 0) && i > 0) {
72 printf("%2X", buf[i]);
73 printf("%2X ", buf[i+1]);
79 static errval_t ip_register(struct devq* q, struct capref cap,
84 struct frame_identity frameid = { .base = 0, .bytes = 0 };
86 struct ip_q* que = (struct ip_q*) q;
88 // Map device registers
89 invoke_frame_identify(cap, &frameid);
91 err = vspace_map_one_frame_attr(&que->regions[rid % MAX_NUM_REGIONS].va,
92 frameid.bytes, cap, VREGION_FLAGS_READ_WRITE,
94 if (err_is_fail(err)) {
95 DEBUG_ERR(err, "vspace_map_one_frame failed");
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);
102 return que->q->f.reg(que->q, cap, rid);
105 static errval_t ip_deregister(struct devq* q, regionid_t rid)
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);
115 static errval_t ip_control(struct devq* q, uint64_t cmd, uint64_t value,
118 struct ip_q* que = (struct ip_q*) q;
119 return que->q->f.ctrl(que->q, cmd, value, result);
123 static errval_t ip_notify(struct devq* q)
125 struct ip_q* que = (struct ip_q*) q;
126 return que->q->f.notify(que->q);
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,
135 // for now limit length
136 // TODO fragmentation
138 struct ip_q* que = (struct ip_q*) q;
139 if (flags & NETIF_TXFLAG) {
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);
147 assert(que->regions[rid % MAX_NUM_REGIONS].va != NULL);
149 uint8_t* start = (uint8_t*) que->regions[rid % MAX_NUM_REGIONS].va +
152 memcpy(start, &que->header, sizeof(que->header));
154 return que->q->f.enq(que->q, rid, offset, length, valid_data,
155 valid_length+sizeof(struct pkt_ip_headers), flags);
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);
166 return NET_QUEUE_ERR_UNKNOWN_BUF_TYPE;
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)
174 struct ip_q* que = (struct ip_q*) q;
176 err = que->q->f.deq(que->q, rid, offset, length, valid_data, valid_length, flags);
177 if (err_is_fail(err)) {
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);
186 struct pkt_ip_headers* header = (struct pkt_ip_headers*)
187 (que->regions[*rid % MAX_NUM_REGIONS].va +
188 *offset + *valid_data);
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);
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);
206 print_buffer(que, que->regions[*rid % MAX_NUM_REGIONS].va + *offset, *valid_length);
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);
216 DEBUG("TX rid: %d offset %ld length %ld \n", *rid, *offset,
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)
233 que = calloc(1, sizeof(struct ip_q));
237 err = net_queue_create(interrupt, card_name, qid, poll, &que->q);
238 if (err_is_fail(err)) {
242 err = devq_init(&que->my_q, false);
243 if (err_is_fail(err)) {
244 // TODO net queue destroy
249 err = devq_control(que->q, 0, 0, &src_mac);
250 if (err_is_fail(err)) {
255 err = net_config_current_ip_query(NET_FLAGS_BLOCKING_INIT, &src_ip);
256 if (err_is_fail(err)) {
260 // fill in header that is reused for each packet
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);
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);
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;
287 que->hdr_len = IP_HLEN + sizeof(struct udp_hdr);
293 USER_PANIC("Unkown protocol specified when creating IP queue \n");
301 errval_t ip_destroy(struct ip_q* q)
303 // TODO destroy q->q;