failure DESCQ_INIT "Failure in descriptor queue init",
};
-errors cpuid UDPQ_ERR_ {
+errors cpuid NET_QUEUE_ERR_ {
failure WRONG_PORT "Received packet with wrong src/dst port",
failure WRONG_IP "Received packet with wrong src/dst IP",
+ failure CHECKSUM "Header checksum failed",
failure NOT_UDP "Received packet is not UDP",
failure UNKNOWN_BUF_TYPE "Neither RX or TX buffer",
};
--- /dev/null
+/*
+ * Copyright (c) 2017 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+#ifndef DEVIF_IP_H_
+#define DEVIF_IP_H_ 1
+
+
+#include <barrelfish/barrelfish.h>
+
+#define UDP_PROT 0
+#define TCP_PROT 1
+
+
+struct ip_q;
+
+struct __attribute__((packed)) eth_addr {
+ uint8_t addr[6];
+};
+
+/**
+ * @param q ip queue to destroy
+ */
+errval_t ip_destroy(struct ip_q* q);
+
+/**
+ * @brief initalized a queue that can send IP packets with a certain requirements.
+ * all other packets received on this queue will be dropped.
+ *
+ * @param q ip queue return value
+ * @param card_name the card name from which a hardware queue will be used
+ * to send IP packets. Internally a queue to the device with
+ * the card_name will be initalized
+ * @param qid the id of the hardware queue (used for filters)
+ * @param prot The protocol that is running on top of IP
+ * @param src_ip Source IP
+ * @param dst_ip Destination IP
+ * @param src_mac Source MAC addressy
+ * @param dst_mac Destination MAC address
+ * @param interrupt Interrupt handler
+ * @param poll If the queue is polled or should use interrupts
+ *
+ */
+errval_t ip_create(struct ip_q** q, const char* card_name, uint64_t* qid,
+ uint8_t prot, uint32_t src_ip, uint32_t dst_ip,
+ struct eth_addr src_mac, struct eth_addr dst_mac,
+ void(*interrupt)(void*), bool poll);
+#endif /* DEVIF_IP_H_ */
#include <barrelfish/barrelfish.h>
+#include <devif/backends/net/ip.h>
struct udp_q;
-
-struct __attribute__((packed)) eth_addr {
- uint8_t addr[6];
-};
/**
* @param q udp queue to destroy
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
-#define ETH_HEADER_LEN 14
+#define ETH_HLEN 14
#define ETHTYPE_IP 0x0800U
#define IP_PROTO_IP 0
#define IP_PROTO_UDP 17
+#define UDP_HLEN 8
+
PACK_STRUCT_BEGIN
struct udp_hdr {
PACK_STRUCT_FIELD(uint16_t src);
--- /dev/null
+--------------------------------------------------------------------------
+-- Copyright (c) 2017, ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for lib/devif/backends/ip
+--
+-- IP backend implemention (including Ethernet)
+--
+--------------------------------------------------------------------------
+
+ [
+ build library { target = "devif_backend_ip",
+ cFiles = [ "devif_backend_ip.c"],
+ addLibraries = libDeps ["devif_internal", "net", "lwip2"],
+ addIncludes = ["/lib/devif/"]
+ }
+ ]
+
+
--- /dev/null
+/*
+ * Copyright (c) 2017, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitätstrasse 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/waitset.h>
+#include <barrelfish/deferred.h>
+#include <devif/queue_interface.h>
+#include <devif/backends/net/ip.h>
+#include <lwip/inet_chksum.h>
+#include <lwip/lwip/inet.h>
+#include <net_interfaces/flags.h>
+#include <net/net.h>
+#include <net/net_queue.h>
+#include <net/net_filter.h>
+#include "../../../queue_interface_internal.h"
+#include "../headers.h"
+
+#define MAX_NUM_REGIONS 64
+
+//#define DEBUG_ENABLED
+
+#if defined(DEBUG_ENABLED)
+#define DEBUG(x...) do { printf("IP_QUEUE: %s.%d:%s:%d: ", \
+ disp_name(), disp_get_core_id(), __func__, __LINE__); \
+ printf(x);\
+ } while (0)
+
+#else
+#define DEBUG(x...) ((void)0)
+#endif
+
+struct region_vaddr {
+ void* va;
+ regionid_t rid;
+};
+
+struct pkt_ip_headers {
+ struct eth_hdr eth;
+ struct ip_hdr ip;
+} __attribute__ ((packed));
+
+struct ip_q {
+ struct devq my_q;
+ struct devq* q;
+ struct pkt_ip_headers header; // can fill in this header and reuse it by copying
+ struct region_vaddr regions[MAX_NUM_REGIONS];
+ struct net_filter_state* filter;
+ uint16_t hdr_len;
+};
+
+
+#ifdef DEBUG_ENABLED
+static void print_buffer(struct ip_q* q, void* start, uint64_t len)
+{
+ uint8_t* buf = (uint8_t*) start;
+ printf("Packet in region at address %p len %zu \n",
+ buf, len);
+ for (int i = 0; i < len; i+=2) {
+ if (((i % 16) == 0) && i > 0) {
+ printf("\n");
+ }
+ printf("%2X", buf[i]);
+ printf("%2X ", buf[i+1]);
+ }
+ printf("\n");
+}
+#endif
+
+static errval_t ip_register(struct devq* q, struct capref cap,
+ regionid_t rid)
+{
+
+ errval_t err;
+ struct frame_identity frameid = { .base = 0, .bytes = 0 };
+
+ struct ip_q* que = (struct ip_q*) q;
+
+ // Map device registers
+ invoke_frame_identify(cap, &frameid);
+
+ err = vspace_map_one_frame_attr(&que->regions[rid % MAX_NUM_REGIONS].va,
+ frameid.bytes, cap, VREGION_FLAGS_READ_WRITE,
+ NULL, NULL);
+ if (err_is_fail(err)) {
+ DEBUG_ERR(err, "vspace_map_one_frame failed");
+ return err;
+ }
+ que->regions[rid % MAX_NUM_REGIONS].rid = rid;
+ DEBUG("id-%d va-%p \n", que->regions[rid % MAX_NUM_REGIONS].rid,
+ que->regions[rid % MAX_NUM_REGIONS].va);
+
+ return que->q->f.reg(que->q, cap, rid);
+}
+
+static errval_t ip_deregister(struct devq* q, regionid_t rid)
+{
+
+ struct ip_q* que = (struct ip_q*) q;
+ que->regions[rid % MAX_NUM_REGIONS].va = NULL;
+ que->regions[rid % MAX_NUM_REGIONS].rid = 0;
+ return que->q->f.dereg(que->q, rid);
+}
+
+
+static errval_t ip_control(struct devq* q, uint64_t cmd, uint64_t value,
+ uint64_t* result)
+{
+ struct ip_q* que = (struct ip_q*) q;
+ return que->q->f.ctrl(que->q, cmd, value, result);
+}
+
+
+static errval_t ip_notify(struct devq* q)
+{
+ struct ip_q* que = (struct ip_q*) q;
+ return que->q->f.notify(que->q);
+}
+
+static errval_t ip_enqueue(struct devq* q, regionid_t rid,
+ genoffset_t offset, genoffset_t length,
+ genoffset_t valid_data, genoffset_t valid_length,
+ uint64_t flags)
+{
+
+ // for now limit length
+ // TODO fragmentation
+
+ struct ip_q* que = (struct ip_q*) q;
+ if (flags & NETIF_TXFLAG) {
+
+ DEBUG("TX rid: %d offset %ld length %ld valid_length %ld \n", rid, offset,
+ length, valid_length);
+ assert(valid_length <= 1500);
+ que->header.ip._len = htons(valid_length + IP_HLEN);
+ que->header.ip._chksum = inet_chksum(&que->header, IP_HLEN);
+
+ assert(que->regions[rid % MAX_NUM_REGIONS].va != NULL);
+
+ uint8_t* start = (uint8_t*) que->regions[rid % MAX_NUM_REGIONS].va +
+ offset + valid_data;
+
+ memcpy(start, &que->header, sizeof(que->header));
+
+ return que->q->f.enq(que->q, rid, offset, length, valid_data,
+ valid_length+sizeof(struct pkt_ip_headers), flags);
+ }
+
+ if (flags & NETIF_RXFLAG) {
+ assert(valid_length <= 2048);
+ DEBUG("RX rid: %d offset %ld length %ld valid_length %ld \n", rid, offset,
+ length, valid_length);
+ return que->q->f.enq(que->q, rid, offset, length, valid_data,
+ valid_length, flags);
+ }
+
+ return NET_QUEUE_ERR_UNKNOWN_BUF_TYPE;
+}
+
+static errval_t ip_dequeue(struct devq* q, regionid_t* rid, genoffset_t* offset,
+ genoffset_t* length, genoffset_t* valid_data,
+ genoffset_t* valid_length, uint64_t* flags)
+{
+ errval_t err;
+ struct ip_q* que = (struct ip_q*) q;
+
+ err = que->q->f.deq(que->q, rid, offset, length, valid_data, valid_length, flags);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ if (*flags & NETIF_RXFLAG) {
+ DEBUG("RX rid: %d offset %ld valid_data %ld length %ld va %p \n", *rid,
+ *offset, *valid_data,
+ *valid_length, que->regions[*rid % MAX_NUM_REGIONS].va + *offset + *valid_data);
+
+ struct pkt_ip_headers* header = (struct pkt_ip_headers*)
+ (que->regions[*rid % MAX_NUM_REGIONS].va +
+ *offset + *valid_data);
+
+ // IP checksum
+ if (header->ip._chksum == inet_chksum(&header->ip, IP_HLEN)) {
+ printf("IP queue: dropping packet wrong checksum \n");
+ err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
+ return err_push(err, NET_QUEUE_ERR_CHECKSUM);
+ }
+
+ // Correct ip for this queue?
+ if (header->ip.src != que->header.ip.dest) {
+ printf("IP queue: dropping packet, wrong IP is %lu should be %lu\n",
+ header->ip.src, que->header.ip.dest);
+ err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
+ return err_push(err, NET_QUEUE_ERR_WRONG_IP);
+ }
+
+#ifdef DEBUG_ENABLED
+ print_buffer(que, que->regions[*rid % MAX_NUM_REGIONS].va + *offset, *valid_length);
+#endif
+
+ *valid_data = IP_HLEN + ETH_HLEN;
+ *valid_length = ntohs(header->ip._len) - IP_HLEN;
+ //print_buffer(que, que->regions[*rid % MAX_NUM_REGIONS].va + *offset+ *valid_data, *valid_length);
+ return SYS_ERR_OK;
+ }
+
+#ifdef DEBUG_ENABLED
+ DEBUG("TX rid: %d offset %ld length %ld \n", *rid, *offset,
+ *valid_length);
+#endif
+
+ return SYS_ERR_OK;
+}
+
+/*
+ * Public functions
+ *
+ */
+errval_t ip_create(struct ip_q** q, const char* card_name, uint64_t* qid,
+ uint8_t prot, uint32_t src_ip, uint32_t dst_ip,
+ struct eth_addr src_mac, struct eth_addr dst_mac,
+ inthandler_t interrupt, bool poll)
+{
+ errval_t err;
+ struct ip_q* que;
+ que = calloc(1, sizeof(struct ip_q));
+ assert(que);
+
+ // init other queue
+ err = net_queue_create(interrupt, card_name, qid, poll, &que->q);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ err = devq_init(&que->my_q, false);
+ if (err_is_fail(err)) {
+ // TODO net queue destroy
+ return err;
+ }
+
+ // fill in header that is reused for each packet
+ // Ethernet
+ memcpy(&(que->header.eth.dest.addr), &dst_mac, ETH_HWADDR_LEN);
+ memcpy(&(que->header.eth.src.addr), &src_mac, ETH_HWADDR_LEN);
+ que->header.eth.type = htons(ETHTYPE_IP);
+
+ // IP
+ que->header.ip._v_hl = 69;
+ IPH_TOS_SET(&que->header.ip, 0x0);
+ IPH_ID_SET(&que->header.ip, htons(0x3));
+ que->header.ip._offset = htons(IP_DF);
+ que->header.ip._proto = 0x11; // IP
+ que->header.ip._ttl = 0x40; // 64
+ que->header.ip.src = htonl(src_ip);
+ que->header.ip.dest = htonl(dst_ip);
+
+ que->my_q.f.reg = ip_register;
+ que->my_q.f.dereg = ip_deregister;
+ que->my_q.f.ctrl = ip_control;
+ que->my_q.f.notify = ip_notify;
+ que->my_q.f.enq = ip_enqueue;
+ que->my_q.f.deq = ip_dequeue;
+ *q = que;
+
+ /*
+ switch(prot) {
+ case UDP_PROT:
+ que->hdr_len = IP_HLEN + sizeof(struct udp_hdr);
+ break;
+ case TCP_PROT:
+ // TODO
+ break;
+ default:
+ USER_PANIC("Unkown protocol specified when creating IP queue \n");
+
+ }
+ */
+
+ return SYS_ERR_OK;
+}
+
+errval_t ip_destroy(struct ip_q* q)
+{
+ // TODO destroy q->q;
+ free(q);
+
+ return SYS_ERR_OK;
+}
+
+
+
[
build library { target = "devif_backend_udp",
cFiles = [ "devif_backend_udp.c"],
- addLibraries = libDeps ["devif_internal", "net", "lwip2"],
+ addLibraries = libDeps ["devif_internal", "net", "lwip2",
+ "devif_backend_ip"],
addIncludes = ["/lib/devif/"]
}
]
#include <lwip/lwip/inet.h>
#include <net_interfaces/flags.h>
#include <net/net.h>
-#include <net/net_queue.h>
#include <net/net_filter.h>
#include "../../../queue_interface_internal.h"
-#include "headers.h"
+#include "../headers.h"
#define MAX_NUM_REGIONS 64
regionid_t rid;
};
-struct pkt_udp_headers {
- struct eth_hdr eth;
- struct ip_hdr ip;
- struct udp_hdr udp;
-} __attribute__ ((packed));
-
struct udp_q {
struct devq my_q;
struct devq* q;
- struct pkt_udp_headers header; // can fill in this header and reuse it by copying
+ struct udp_hdr header; // can fill in this header and reuse it by copying
struct region_vaddr regions[MAX_NUM_REGIONS];
struct net_filter_state* filter;
};
DEBUG("TX rid: %d offset %ld length %ld valid_length %ld \n", rid, offset,
length, valid_length);
assert(valid_length <= 1500);
- que->header.udp.len = htons(valid_length + sizeof(struct udp_hdr));
- que->header.ip._len = htons(valid_length + sizeof(struct udp_hdr) + IP_HLEN);
- que->header.ip._chksum = inet_chksum(&que->header.ip, IP_HLEN);
+ que->header.len = htons(valid_length + UDP_HLEN);
assert(que->regions[rid % MAX_NUM_REGIONS].va != NULL);
uint8_t* start = (uint8_t*) que->regions[rid % MAX_NUM_REGIONS].va +
- offset + valid_data;
+ offset + valid_data + ETH_HLEN + IP_HLEN;
memcpy(start, &que->header, sizeof(que->header));
return que->q->f.enq(que->q, rid, offset, length, valid_data,
- valid_length+sizeof(struct pkt_udp_headers), flags);
+ valid_length + UDP_HLEN, flags);
}
if (flags & NETIF_RXFLAG) {
valid_length, flags);
}
- return UDPQ_ERR_UNKNOWN_BUF_TYPE;
+ return NET_QUEUE_ERR_UNKNOWN_BUF_TYPE;
}
static errval_t udp_dequeue(struct devq* q, regionid_t* rid, genoffset_t* offset,
*offset, *valid_data,
*valid_length, que->regions[*rid % MAX_NUM_REGIONS].va + *offset + *valid_data);
- struct pkt_udp_headers* header = (struct pkt_udp_headers*)
- (que->regions[*rid % MAX_NUM_REGIONS].va +
- *offset + *valid_data);
+ struct udp_hdr* header = (struct udp_hdr*)
+ (que->regions[*rid % MAX_NUM_REGIONS].va +
+ *offset + *valid_data);
- // is this a UPD packet
- if (header->ip._proto != 0x11) {
- printf("UDP queue: dropping packet, not udp %d \n",
- header->ip._proto);
- err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
- return err_push(err, UDPQ_ERR_NOT_UDP);
- }
-
- // IP checksum
- if (header->ip._chksum == inet_chksum(&header->ip, IP_HLEN)) {
- printf("UDP queue: dropping packet wrong checksum \n");
- err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
- return err_push(err, UDPQ_ERR_NOT_UDP);
- }
-
// Correct port for this queue?
- if (header->udp.dest != que->header.udp.dest) {
+ if (header->dest != que->header.dest) {
printf("UDP queue: dropping packet, wrong port %d %d \n",
- header->udp.dest, que->header.udp.dest);
+ header->dest, que->header.dest);
err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
- return err_push(err, UDPQ_ERR_WRONG_PORT);
- }
-
- // Correct ip for this queue?
- if (header->ip.src != que->header.ip.dest) {
- printf("UDP queue: dropping packet, wrong IP is %lu should be %lu\n",
- header->ip.src, que->header.ip.dest);
- //print_buffer(que, header, *valid_length);
- //print_buffer(que, &que->header, sizeof(que->header));
- err = que->q->f.enq(que->q, *rid, *offset, *length, 0, 0, NETIF_RXFLAG);
- return err_push(err, UDPQ_ERR_WRONG_IP);
+ return err_push(err, NET_QUEUE_ERR_WRONG_PORT);
}
#ifdef DEBUG_ENABLED
print_buffer(que, que->regions[*rid % MAX_NUM_REGIONS].va + *offset, *valid_length);
#endif
- *valid_data += sizeof(que->header);
- *valid_length = ntohs(header->udp.len) - sizeof(que->header.udp);
+ *valid_length = ntohs(header->len) - UDP_HLEN - IP_HLEN - ETH_HLEN;
+ *valid_data += UDP_HLEN;
//print_buffer(que, que->regions[*rid % MAX_NUM_REGIONS].va + *offset+ *valid_data, *valid_length);
return SYS_ERR_OK;
}
uint16_t src_port, uint16_t dst_port,
uint32_t src_ip, uint32_t dst_ip,
struct eth_addr src_mac, struct eth_addr dst_mac,
- inthandler_t interrupt, bool poll)
+ void(*interrupt)(void*), bool poll)
{
errval_t err;
struct udp_q* que;
// init other queue
uint64_t qid;
- err = net_queue_create(interrupt, card_name, &qid, poll, &que->q);
+ err = ip_create((struct ip_q**) &que->q, card_name, &qid, UDP_PROT, src_ip, dst_ip,
+ src_mac, dst_mac, interrupt, poll);
if (err_is_fail(err)) {
return err;
}
if (err_is_fail(err)) {
return err;
}
-
+
struct net_filter_ip ip = {
.qid = qid,
.ip_src = dst_ip,
return err;
}
- // fill in header that is reused for each packet
- // Ethernet
- memcpy(&(que->header.eth.dest.addr), &dst_mac, ETH_HWADDR_LEN);
- memcpy(&(que->header.eth.src.addr), &src_mac, ETH_HWADDR_LEN);
- que->header.eth.type = htons(ETHTYPE_IP);
-
- // IP
- que->header.ip._v_hl = 69;
- IPH_TOS_SET(&que->header.ip, 0x0);
- IPH_ID_SET(&que->header.ip, htons(0x3));
- que->header.ip._offset = htons(IP_DF);
- que->header.ip._proto = 0x11; // UDP
- que->header.ip._ttl = 0x40; // 64
- que->header.ip.src = htonl(src_ip);
- que->header.ip.dest = htonl(dst_ip);
-
// UDP fields
- que->header.udp.src = htons(src_port);
- que->header.udp.dest = htons(dst_port);
- que->header.udp.chksum = 0x0;
-
+ que->header.src = htons(src_port);
+ que->header.dest = htons(dst_port);
+ que->header.chksum = 0x0;
que->my_q.f.reg = udp_register;
que->my_q.f.dereg = udp_deregister;
{
assert(len <= 1500);
if (q->regions[rid % MAX_NUM_REGIONS].va != NULL) {
- uint8_t* start = q->regions[rid % MAX_NUM_REGIONS].va + offset;
- memcpy(start + sizeof(struct pkt_udp_headers), data, len);
+ uint8_t* start = q->regions[rid % MAX_NUM_REGIONS].va + offset
+ + sizeof (struct udp_hdr)
+ + sizeof (struct ip_hdr)
+ + sizeof (struct eth_hdr);
+ memcpy(start, data, len);
return SYS_ERR_OK;
} else {
return DEVQ_ERR_INVALID_REGION_ARGS;