1254721Semaste/** 2254721Semaste * \file 3254721Semaste * \brief LWIP test/demo code 4254721Semaste */ 5254721Semaste 6254721Semaste/* 7254721Semaste * Copyright (c) 2013, University of Washington. 8254721Semaste * All rights reserved. 9254721Semaste * 10254721Semaste * This file is distributed under the terms in the attached LICENSE file. 11254721Semaste * If you do not find this file, copies can be found by writing to: 12254721Semaste * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13254721Semaste */ 14254721Semaste 15254721Semaste#include <stdio.h> 16254721Semaste#include <assert.h> 17254721Semaste#include <barrelfish/barrelfish.h> 18254721Semaste#include <netif/e1000.h> 19254721Semaste#include <netif/etharp.h> 20254721Semaste#include <lwip/ip.h> 21254721Semaste#include <lwip/udp.h> 22254721Semaste 23254721Semastestatic ether_terminate_queue ether_terminate_queue_ptr = NULL; 24254721Semastestatic ether_get_mac_address_t ether_get_mac_address_ptr = NULL; 25254721Semastestatic ether_transmit_pbuf_list_t ether_transmit_pbuf_list_ptr = NULL; 26254721Semastestatic ether_get_tx_free_slots tx_free_slots_fn_ptr = NULL; 27254721Semastestatic ether_handle_free_TX_slot handle_free_tx_slot_fn_ptr = NULL; 28254721Semastestatic ether_rx_register_buffer rx_register_buffer_fn_ptr = NULL; 29254721Semastestatic ether_rx_get_free_slots rx_get_free_slots_fn_ptr = NULL; 30254721Semaste 31254721Semasteuint64_t interrupt_counter = 0; 32254721Semasteuint64_t total_rx_p_count = 0; 33254721Semasteuint64_t total_rx_datasize = 0; 34254721Semastestruct client_closure *g_cl = NULL; 35254721Semaste 36254721Semaste#define MAX_PACKETS 256 37254721Semaste#define PACKET_SIZE 2048 38254721Semaste 39254721Semastestruct packet { 40254721Semaste uint8_t *payload; 41254721Semaste lpaddr_t pa; 42254721Semaste size_t len; 43254721Semaste}; 44254721Semaste 45254721Semastestatic struct packet rx_packets[MAX_PACKETS], tx_packets[MAX_PACKETS]; 46254721Semaste 47254721Semastevoid ethernetif_backend_init(char *service_name, uint64_t queueid, 48254721Semaste ether_get_mac_address_t get_mac_ptr, 49254721Semaste ether_terminate_queue terminate_queue_ptr, 50254721Semaste ether_transmit_pbuf_list_t transmit_ptr, 51254721Semaste ether_get_tx_free_slots tx_free_slots_ptr, 52254721Semaste ether_handle_free_TX_slot handle_free_tx_slot_ptr, 53254721Semaste size_t rx_bufsz, 54254721Semaste ether_rx_register_buffer rx_register_buffer_ptr, 55254721Semaste ether_rx_get_free_slots rx_get_free_slots_ptr) 56254721Semaste{ 57254721Semaste ether_terminate_queue_ptr = terminate_queue_ptr; 58254721Semaste ether_get_mac_address_ptr = get_mac_ptr; 59254721Semaste ether_transmit_pbuf_list_ptr = transmit_ptr; 60254721Semaste tx_free_slots_fn_ptr = tx_free_slots_ptr; 61254721Semaste handle_free_tx_slot_fn_ptr = handle_free_tx_slot_ptr; 62254721Semaste rx_register_buffer_fn_ptr = rx_register_buffer_ptr; 63254721Semaste rx_get_free_slots_fn_ptr = rx_get_free_slots_ptr; 64254721Semaste /* printf("PBUF_POOL_BUFSIZE = %u, rx buffer size = %zu\n", PBUF_POOL_BUFSIZE, */ 65254721Semaste /* rx_bufsz); */ 66254721Semaste} 67254721Semaste 68254721Semastestatic struct packet *get_tx_packet(void) 69254721Semaste{ 70254721Semaste static unsigned int idx = 0; 71254721Semaste struct packet *p = &tx_packets[idx]; 72254721Semaste 73254721Semaste // Busy-wait until packet not in flight 74254721Semaste while(p->len != 0) { 75254721Semaste handle_free_tx_slot_fn_ptr(); 76254721Semaste } 77254721Semaste 78254721Semaste idx = (idx + 1) % MAX_PACKETS; 79254721Semaste return p; 80254721Semaste} 81254721Semaste 82254721Semastestatic void packet_output(struct packet *p) 83254721Semaste{ 84254721Semaste struct driver_buffer buf; 85254721Semaste 86254721Semaste buf.pa = p->pa; 87254721Semaste buf.va = p->payload; 88254721Semaste buf.len = p->len; 89254721Semaste buf.flags = 0; 90254721Semaste buf.opaque = p; 91254721Semaste 92254721Semaste errval_t err = ether_transmit_pbuf_list_ptr(&buf, 1); 93254721Semaste assert(err_is_ok(err)); 94254721Semaste} 95254721Semaste 96254721Semaste#include <barrelfish/sys_debug.h> 97254721Semaste 98254721Semaste// This is roughly Mon Apr 25 13:50 CEST 2011 99254721Semaste#define TOD_OFFSET 1303732456ULL 100254721Semaste 101254721Semasteint gettimeofday(struct timeval *tv, struct timezone *tz) 102254721Semaste{ 103254721Semaste uint64_t now = rdtsc(); 104254721Semaste static uint64_t tscperms = 0; 105254721Semaste 106254721Semaste if(tscperms == 0) { 107254721Semaste errval_t err = sys_debug_get_tsc_per_ms(&tscperms); 108254721Semaste assert(err_is_ok(err)); 109254721Semaste assert(tscperms >= 1000); 110254721Semaste } 111254721Semaste 112254721Semaste uint64_t tod_us = (TOD_OFFSET * 1000000) + (now / (tscperms / 1000)); 113254721Semaste 114254721Semaste if(tv != NULL) { 115254721Semaste tv->tv_sec = tod_us / 1000000; 116254721Semaste tv->tv_usec = tod_us % 1000000; 117254721Semaste } 118254721Semaste 119254721Semaste assert(tz == NULL); 120254721Semaste if(tz != NULL) { 121254721Semaste } 122254721Semaste 123254721Semaste return 0; 124254721Semaste} 125254721Semaste 126254721Semaste#define MAX_STAMPS 10000 127254721Semaste 128254721Semastestatic uint64_t tstamp[MAX_STAMPS]; 129254721Semastestatic int stamps = 0; 130254721Semaste 131254721Semastevoid process_received_packet(struct driver_rx_buffer *buffer, size_t count, 132254721Semaste uint64_t flags) 133254721Semaste{ 134254721Semaste uint64_t instamp = rdtsc(); 135254721Semaste 136254721Semaste struct packet *p = buffer->opaque; 137254721Semaste assert(p != NULL); 138254721Semaste assert(count == 1); 139254721Semaste p->len = buffer->len; 140254721Semaste 141254721Semaste /* printf("Incoming packet\n"); */ 142254721Semaste 143254721Semaste // Drop packets with invalid checksums 144254721Semaste if(flags & NETIF_RXFLAG_IPCHECKSUM) { 145254721Semaste if(!(flags & NETIF_RXFLAG_IPCHECKSUM_GOOD)) { 146254721Semaste goto out; 147254721Semaste } 148254721Semaste } 149254721Semaste 150254721Semaste if(flags & NETIF_RXFLAG_L4CHECKSUM) { 151254721Semaste if(!(flags & NETIF_RXFLAG_L4CHECKSUM_GOOD)) { 152254721Semaste goto out; 153254721Semaste } 154254721Semaste } 155254721Semaste 156254721Semaste /* printf("Checksum good\n"); */ 157254721Semaste 158254721Semaste struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; 159254721Semaste switch (htons(ethhdr->type)) { 160254721Semaste case ETHTYPE_ARP: 161254721Semaste { 162254721Semaste /* printf("Is an ARP packet\n"); */ 163254721Semaste struct etharp_hdr *arphdr = (struct etharp_hdr *)(p->payload + SIZEOF_ETH_HDR); 164254721Semaste struct eth_addr mymac; 165254721Semaste bool ourarp = false; 166254721Semaste 167254721Semaste if(htons(arphdr->opcode) == ARP_REQUEST) { 168254721Semaste // 10.0.2.15 169254721Semaste if(htons(arphdr->dipaddr.addrw[0]) == 0x0a00 && 170254721Semaste htons(arphdr->dipaddr.addrw[1]) == 0x020f) { 171254721Semaste memcpy(&mymac.addr, "\x52\x54\x00\x12\x34\x56", ETHARP_HWADDR_LEN); 172254721Semaste ourarp = true; 173254721Semaste } else if(htons(arphdr->dipaddr.addrw[0]) == 0x80d0 && 174254721Semaste htons(arphdr->dipaddr.addrw[1]) == 0x0643) { 175254721Semaste memcpy(&mymac.addr, "\xa0\x36\x9f\x10\x00\xa6", ETHARP_HWADDR_LEN); 176254721Semaste ourarp = true; 177254721Semaste } 178254721Semaste } 179254721Semaste 180254721Semaste if(ourarp) { 181254721Semaste /* printf("ARP request for us\n"); */ 182254721Semaste // Send reply 183254721Semaste struct packet *outp = get_tx_packet(); 184254721Semaste struct eth_hdr *myeth = (struct eth_hdr *)outp->payload; 185254721Semaste struct etharp_hdr *myarp = (struct etharp_hdr *)(outp->payload + SIZEOF_ETH_HDR); 186254721Semaste 187254721Semaste // ETH header 188254721Semaste memcpy(&myeth->dest, &arphdr->shwaddr, ETHARP_HWADDR_LEN); 189254721Semaste memcpy(&myeth->src, &mymac, ETHARP_HWADDR_LEN); 190254721Semaste myeth->type = htons(ETHTYPE_ARP); 191254721Semaste 192254721Semaste // ARP header 193254721Semaste myarp->hwtype = htons(1); 194254721Semaste myarp->proto = htons(ETHTYPE_IP); 195254721Semaste myarp->hwlen = 6; 196254721Semaste myarp->protolen = 4; 197254721Semaste myarp->opcode = htons(ARP_REPLY); 198254721Semaste memcpy(&myarp->shwaddr, &mymac, ETHARP_HWADDR_LEN); 199254721Semaste memcpy(&myarp->sipaddr, &arphdr->dipaddr, sizeof(myarp->sipaddr)); 200254721Semaste memcpy(&myarp->dhwaddr, &arphdr->shwaddr, ETHARP_HWADDR_LEN); 201254721Semaste memcpy(&myarp->dipaddr, &arphdr->sipaddr, sizeof(myarp->dipaddr)); 202254721Semaste 203254721Semaste outp->len = p->len; 204254721Semaste packet_output(outp); 205254721Semaste } 206254721Semaste } 207254721Semaste break; 208254721Semaste 209254721Semaste case ETHTYPE_IP: 210254721Semaste { 211254721Semaste struct ip_hdr *iphdr = (struct ip_hdr *)(p->payload + SIZEOF_ETH_HDR); 212254721Semaste 213254721Semaste /* printf("Is an IP packet, type %x\n", IPH_PROTO(iphdr)); */ 214254721Semaste 215254721Semaste if(IPH_PROTO(iphdr) == IP_PROTO_UDP) { 216254721Semaste struct udp_hdr *udphdr = (struct udp_hdr *)(p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4)); 217254721Semaste uint8_t *payload = p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr); 218254721Semaste 219254721Semaste /* printf("Got UDP packet, dest IP %x, dest port %u\n", */ 220254721Semaste /* iphdr->dest.addr, udphdr->dest); */ 221254721Semaste 222254721Semaste if(htonl(iphdr->dest.addr) != 0x80d00643 || 223254721Semaste htons(udphdr->dest) != 1234) { 224254721Semaste goto out; 225254721Semaste } 226254721Semaste 227254721Semaste /* printf("payload '%s'\n", payload); */ 228254721Semaste 229254721Semaste struct packet *outp = get_tx_packet(); 230254721Semaste struct eth_hdr *myeth = (struct eth_hdr *)outp->payload; 231254721Semaste struct ip_hdr *myip = (struct ip_hdr *)(outp->payload + SIZEOF_ETH_HDR); 232254721Semaste struct udp_hdr *myudp = (struct udp_hdr *)(outp->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4)); 233254721Semaste uint8_t *mypayload = outp->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr); 234254721Semaste 235254721Semaste // ETH header 236254721Semaste memcpy(&myeth->dest, ðhdr->src, ETHARP_HWADDR_LEN); 237254721Semaste memcpy(&myeth->src, ðhdr->dest, ETHARP_HWADDR_LEN); 238254721Semaste myeth->type = htons(ETHTYPE_IP); 239254721Semaste 240254721Semaste // IP header 241254721Semaste memcpy(myip, iphdr, sizeof(struct ip_hdr)); 242254721Semaste memcpy(&myip->src, &iphdr->dest, sizeof(ip_addr_p_t)); 243254721Semaste memcpy(&myip->dest, &iphdr->src, sizeof(ip_addr_p_t)); 244254721Semaste 245254721Semaste // UDP header 246254721Semaste memcpy(myudp, udphdr, sizeof(struct udp_hdr)); 247254721Semaste myudp->src = udphdr->dest; 248254721Semaste myudp->dest = udphdr->src; 249254721Semaste 250254721Semaste // Payload 251254721Semaste memcpy(mypayload, payload, htons(udphdr->len) - 8); 252254721Semaste 253254721Semaste outp->len = p->len; 254254721Semaste packet_output(outp); 255254721Semaste 256254721Semaste uint64_t now = rdtsc(); 257254721Semaste tstamp[stamps] = now - instamp; 258254721Semaste 259254721Semaste /* printf("got packet %d\n", stamps); */ 260254721Semaste 261254721Semaste stamps++; 262254721Semaste if(stamps == MAX_STAMPS) { 263254721Semaste printf("latencies:\n"); 264254721Semaste for(int i = 0; i < MAX_STAMPS; i++) { 265254721Semaste printf("%" PRIu64 " cycles\n", tstamp[i]); 266254721Semaste } 267254721Semaste stamps = 0; 268254721Semaste } 269254721Semaste 270254721Semaste } 271254721Semaste } 272254721Semaste break; 273254721Semaste 274254721Semaste default: 275 break; 276 } 277 278 out: 279 { 280 //now we have consumed the preregistered pbuf containing a received packet 281 //which was processed in this function. Therefore we have to register a new 282 //free buffer for receiving packets. 283 errval_t err = rx_register_buffer_fn_ptr(p->pa, p->payload, p); 284 assert(err_is_ok(err)); 285 } 286} 287 288bool handle_tx_done(void *opaque) 289{ 290 struct packet *p = opaque; 291 p->len = 0; 292 return true; 293} 294 295/* allocate a single frame, mapping it into our vspace with given attributes */ 296static void *alloc_map_frame(vregion_flags_t attr, size_t size, struct capref *retcap) 297{ 298 struct capref frame; 299 errval_t r; 300 301 r = frame_alloc(&frame, size, NULL); 302 assert(err_is_ok(r)); 303 void *va; 304 r = vspace_map_one_frame_attr(&va, size, frame, attr, 305 NULL, NULL); 306 if (err_is_fail(r)) { 307 DEBUG_ERR(r, "vspace_map_one_frame failed"); 308 return NULL; 309 } 310 311 if (retcap != NULL) { 312 *retcap = frame; 313 } 314 315 return va; 316} 317 318int main(int argc, char *argv[]) 319{ 320 uint8_t mac[6]; 321 322 printf("Starting e10k test program...\n"); 323 324 e1000n_driver_init(argc, argv); 325 326 ether_get_mac_address_ptr(mac); 327 printf("e10ktest MAC address %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", 328 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 329 330 struct capref frame; 331 uint8_t *ram_base = alloc_map_frame(VREGION_FLAGS_READ_WRITE, 332 MAX_PACKETS * PACKET_SIZE, &frame); 333 assert(ram_base != NULL); 334 335 struct frame_identity id; 336 errval_t err = frame_identify(frame, &id); 337 assert(err_is_ok(err)); 338 339 // Add buffers to RX ring for packet reception 340 for(int i = 0; i < MAX_PACKETS; i++) { 341 struct packet *p = &rx_packets[i]; 342 343 p->payload = ram_base + (i * PACKET_SIZE); 344 p->pa = id.base + (i * PACKET_SIZE); 345 p->len = PACKET_SIZE; 346 347 err = rx_register_buffer_fn_ptr(p->pa, p->payload, p); 348 assert(err_is_ok(err)); 349 } 350 351 // Setup TX packets 352 ram_base = alloc_map_frame(VREGION_FLAGS_READ_WRITE, 353 MAX_PACKETS * PACKET_SIZE, &frame); 354 assert(ram_base != NULL); 355 err = frame_identify(frame, &id); 356 assert(err_is_ok(err)); 357 for(int i = 0; i < MAX_PACKETS; i++) { 358 struct packet *p = &tx_packets[i]; 359 p->payload = ram_base + (i * PACKET_SIZE); 360 p->pa = id.base + (i * PACKET_SIZE); 361 p->len = 0; 362 } 363 364 for(;;) { 365 e1000n_polling_loop(get_default_waitset()); 366 } 367 368 return 0; 369} 370