1/*
2 * Copyright (c) 2014, University of Washington.
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, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich.
8 * Attn: Systems Group.
9 */
10
11#include <stdio.h>
12#include <assert.h>
13#include <barrelfish/barrelfish.h>
14#include <barrelfish/inthandler.h>
15#include <barrelfish/sys_debug.h>
16#include <skb/skb.h>
17#include <sys/socket.h>
18#include <netif/e1000.h>
19#include <limits.h>
20#include <barrelfish/waitset.h>
21#include <barrelfish/waitset_chan.h>
22#include <lwip/sock_chan_support.h>
23#include <netdb.h>
24#include <arranet.h>
25#include <arranet_impl.h>
26#include <acpi_client/acpi_client.h>
27#include <arranet_debug.h>
28
29static ether_terminate_queue ether_terminate_queue_ptr = NULL;
30static ether_get_mac_address_t ether_get_mac_address_ptr = NULL;
31static ether_transmit_pbuf_list_t ether_transmit_pbuf_list_ptr = NULL;
32static ether_get_tx_free_slots tx_free_slots_fn_ptr = NULL;
33static ether_handle_free_TX_slot handle_free_tx_slot_fn_ptr = NULL;
34static ether_rx_register_buffer rx_register_buffer_fn_ptr = NULL;
35static ether_rx_get_free_slots rx_get_free_slots_fn_ptr = NULL;
36
37uint64_t interrupt_counter = 0;
38uint64_t total_rx_p_count = 0;
39uint64_t total_rx_datasize = 0;
40struct client_closure *g_cl = NULL;
41
42#define MAX_PACKETS     2000
43#define PACKET_SIZE     2048
44#define MAX_PEERS       256
45
46static int use_vtd = 0;
47static int vtd_coherency = 1;
48
49struct peer {
50    uint32_t ip;
51    struct eth_addr mac;
52};
53
54// Configure static ARP entries here
55// IP addresses are in network byte order!
56static struct peer peers[MAX_PEERS] = {
57    {
58        // XXX: This needs to be updated each time the tap interface is re-initialized
59        .ip = 0x0102000a,       // 10.0.2.1
60        /* .mac.addr = "\x86\x86\x0b\xda\x22\xd7", */
61        .mac.addr = "\x12\x67\xb9\x3e\xe2\x2c",
62    },
63    {
64        // XXX: This needs to be updated each time the tap interface is re-initialized
65        .ip = 0x0164a8c0,       // 192.168.100.1
66        .mac.addr = "\x5e\x93\xf2\xf1\xeb\xfa",
67    },
68    {
69        .ip = 0xaf06d080,       // 128.208.6.175 - swingout2
70        .mac.addr = "\x90\xe2\xba\x3a\x2e\xdd",
71    },
72    {
73        .ip = 0xec06d080,       // 128.208.6.236 - swingout3
74        .mac.addr = "\xa0\x36\x9f\x0f\xfb\xe2",
75    },
76    {
77        .ip = 0x8106d080,       // 128.208.6.129 - swingout4
78        .mac.addr = "\xa0\x36\x9f\x10\x01\x6e",
79    },
80    {
81        .ip = 0x8206d080,       // 128.208.6.130 - swingout5
82        .mac.addr = "\xa0\x36\x9f\x10\x00\xa2",
83    },
84    {
85        .ip = 0xc506d080,       // 128.208.6.197 - swingout6
86        .mac.addr = "\xa0\x36\x9f\x10\x03\x52",
87    },
88};
89static int peers_alloc = 7;             // Set number of static ARP here!
90
91struct pkt_ip_headers {
92    struct eth_hdr eth;
93    struct ip_hdr ip;
94} __attribute__ ((packed));
95
96struct pkt_udp_headers {
97    struct eth_hdr eth;
98    struct ip_hdr ip;
99    struct udp_hdr udp;
100} __attribute__ ((packed));
101
102struct pkt_tcp_headers {
103    struct eth_hdr eth;
104    struct ip_hdr ip;
105    struct tcp_hdr tcp;
106} __attribute__ ((packed));
107
108static struct packet rx_packets[MAX_PACKETS];
109
110/******** IP config *********/
111
112struct mac2ip {
113    uint8_t mac[ETHARP_HWADDR_LEN];
114    uint32_t ip;
115};
116
117static struct mac2ip ip_config[] = {
118    {   // QEMU
119        .mac = "\x52\x54\x00\x12\x34\x56",
120        /* .ip = 0x0a00020f,       // 10.0.2.15 */
121        .ip = 0xc0a8640f,       // 192.168.100.15
122    },
123    {
124        // QEMU2
125        .mac = "\x52\x54\x00\x12\x34\x57",
126        .ip = 0xc0a80102,       // 192.168.1.2
127    },
128    {   // swingout1 (and swingout1-vf0)
129        .mac = "\xa0\x36\x9f\x10\x00\xa6",
130        .ip = 0x80d00643,       // 128.208.6.67
131    },
132    {   // swingout1-vf1
133        .mac = "\x22\xc9\xfc\x96\x83\xfc",
134        .ip = 0x80d00644,       // 128.208.6.68
135    },
136    {   // swingout1-vf2
137        .mac = "\xce\x43\x5b\xf7\x3e\x60",
138        .ip = 0x80d00602,       // 128.208.6.2
139    },
140    {   // swingout1-vf3
141        .mac = "\x6a\xb0\x62\xf6\xa7\x21",
142        .ip = 0x80d00603,       // 128.208.6.3
143    },
144    {   // swingout1-vf4
145        .mac = "\xb2\xdf\xf9\x39\xc6\x10",
146        .ip = 0x80d00604,       // 128.208.6.4
147    },
148    {   // swingout1-vf5
149        .mac = "\x92\x77\xe7\x3f\x80\x30",
150        .ip = 0x80d0060c,       // 128.208.6.12
151    },
152    {   // swingout5
153        .mac = "\xa0\x36\x9f\x10\x00\xa2",
154        .ip = 0x80d00682,       // 128.208.6.130
155    },
156};
157
158static uint8_t arranet_mymac[ETHARP_HWADDR_LEN];
159static uint32_t arranet_myip = 0;
160
161void ethernetif_backend_init(char *service_name, uint64_t queueid,
162                             ether_get_mac_address_t get_mac_ptr,
163                             ether_terminate_queue terminate_queue_ptr,
164                             ether_transmit_pbuf_list_t transmit_ptr,
165                             ether_get_tx_free_slots tx_free_slots_ptr,
166                             ether_handle_free_TX_slot handle_free_tx_slot_ptr,
167                             size_t rx_bufsz,
168                             ether_rx_register_buffer rx_register_buffer_ptr,
169                             ether_rx_get_free_slots rx_get_free_slots_ptr)
170{
171    ether_terminate_queue_ptr = terminate_queue_ptr;
172    ether_get_mac_address_ptr = get_mac_ptr;
173    ether_transmit_pbuf_list_ptr = transmit_ptr;
174    tx_free_slots_fn_ptr = tx_free_slots_ptr;
175    handle_free_tx_slot_fn_ptr = handle_free_tx_slot_ptr;
176    rx_register_buffer_fn_ptr = rx_register_buffer_ptr;
177    rx_get_free_slots_fn_ptr = rx_get_free_slots_ptr;
178    /* printf("PBUF_POOL_BUFSIZE = %u, rx buffer size = %zu\n", PBUF_POOL_BUFSIZE, */
179    /*        rx_bufsz); */
180}
181
182#define MAX_DRIVER_BUFS         16
183
184static genpaddr_t rx_pbase = 0, tx_pbase = 0;
185static genvaddr_t rx_vbase = 0, tx_vbase = 0;
186
187static struct packet tx_packets[MAX_PACKETS];
188/* static uint8_t tx_bufs[MAX_PACKETS][PACKET_SIZE]; */
189static unsigned int tx_idx = 0;
190/* static ssize_t tx_packets_available = MAX_PACKETS; */
191
192#include <barrelfish/deferred.h>
193
194static void packet_output(struct packet *p)
195{
196    struct driver_buffer bufs[MAX_DRIVER_BUFS];
197    int n = 0;
198
199    for (struct packet *q = p; q != NULL; q = q->next) {
200        struct driver_buffer *buf = &bufs[n];
201
202        /* if(q->payload < &tx_bufs[0][0] || q->payload >= &tx_bufs[MAX_PACKETS][PACKET_SIZE]) { */
203        /*     printf("Called from %p %p\n", */
204        /*            __builtin_return_address(0), */
205        /*            __builtin_return_address(1)); */
206        /*     assert(q->payload >= &tx_bufs[0][0] && q->payload < &tx_bufs[MAX_PACKETS][PACKET_SIZE]); */
207        /* } */
208
209        /* Send the data from the pbuf to the interface, one pbuf at a
210           time. The size of the data in each pbuf is kept in the ->len
211           variable. */
212        assert(q->len > 0);
213
214        // Check if it's from the RX region
215        /* printf("RX region: Comparing %p against [%p:%p]\n", */
216        /*        q->payload, */
217        /*        (void *)rx_vbase, */
218        /*        (void *)(rx_vbase + (MAX_PACKETS * PACKET_SIZE + 4096))); */
219        if (!use_vtd) {
220            if(((genvaddr_t)q->payload) >= rx_vbase &&
221                    ((genvaddr_t)q->payload) < rx_vbase + (MAX_PACKETS * PACKET_SIZE + 4096)) {
222                buf->pa = rx_pbase + ((genvaddr_t)q->payload - rx_vbase);
223            } else if(((genvaddr_t)q->payload) >= tx_vbase &&
224                    ((genvaddr_t)q->payload) < tx_vbase + (MAX_PACKETS * PACKET_SIZE)) {
225                // It is from the TX region!
226                buf->pa = tx_pbase + ((genvaddr_t)q->payload - tx_vbase);
227            } else {
228                // Check if it's in morecore's region
229                struct morecore_state *mc_state = get_morecore_state();
230                struct vspace_mmu_aware *mmu_state = &mc_state->mmu_state;
231                genvaddr_t base = vregion_get_base_addr(&mmu_state->vregion);
232                struct memobj_frame_list *i;
233
234                // Walk frame list
235                for(i = mmu_state->memobj.frame_list; i != NULL; i = i->next) {
236                    // If address is completely within frame, we can resolve
237                    // XXX: Everything else would be easier with an IOMMU
238                    /* printf("Heap: Comparing [%p:%p] against [%p:%p]\n", */
239                    /*        q->payload, q->payload + q->len, */
240                    /*        (void *)(base + i->offset), */
241                    /*        (void *)(base + i->offset + i->size)); */
242                    if(base + i->offset <= (genvaddr_t)q->payload &&
243                            ((genvaddr_t)q->payload) + q->len < base + i->offset + i->size) {
244                        assert(i->pa != 0);
245
246                        /* buf->pa = id.base + ((genvaddr_t)q->payload - base - i->offset); */
247                        buf->pa = i->pa + ((genvaddr_t)q->payload - base - i->offset);
248                        break;
249                    }
250                }
251
252                if(i == NULL) {
253                    // Check if it's in text/data region
254                    int entry;
255                    for(entry = 0; entry < mc_state->v2p_entries; entry++) {
256                        struct v2pmap *pmap = &mc_state->v2p_mappings[entry];
257
258                        // If address is completely within frame, we can resolve
259                        // XXX: Everything else would be easier with an IOMMU
260                        /* printf("BSS: Comparing [%p:%p] against [%p:%p]\n", */
261                        /*        q->payload, q->payload + q->len, */
262                        /*        (void *)(pmap->va), */
263                        /*        (void *)(pmap->va + pmap->size)); */
264                        if(pmap->va <= (genvaddr_t)q->payload &&
265                                ((genvaddr_t)q->payload) + q->len < pmap->va + pmap->size) {
266                            buf->pa = pmap->pa + ((genvaddr_t)q->payload - pmap->va);
267                            break;
268                        }
269
270                    }
271
272                    if(entry == mc_state->v2p_entries) {
273                        printf("Called from %p %p %p\n",
274                                __builtin_return_address(0),
275                                __builtin_return_address(1),
276                                __builtin_return_address(2));
277
278                        USER_PANIC("Invalid pbuf! payload = %p, pa = %p, subpacket = %d\n",
279                                q->payload, buf->pa, n);
280                    }
281                }
282            }
283        }
284        /* printf("Sending: '%s'\n", (char *)q->payload); */
285
286        buf->va = q->payload;
287        buf->len = q->len;
288#ifndef SENDMSG_WITH_COPY
289        buf->opaque = q->opaque;
290#else
291        buf->opaque = q;
292#endif
293        buf->flags = q->flags;
294
295        n++;
296    }
297
298    errval_t err = ether_transmit_pbuf_list_ptr(bufs, n);
299    assert(err_is_ok(err));
300}
301
302static struct pkt_ip_headers packet_ip_header;
303static struct pkt_udp_headers packet_udp_header;
304static struct pkt_tcp_headers packet_tcp_header;
305
306static struct peer *peers_get_from_ip(uint32_t ip)
307{
308    for(int i = 0; i < MAX_PEERS; i++) {
309        if(ip == peers[i].ip) {
310            return &peers[i];
311        }
312    }
313
314    /* printf("NOT FOUND: %x\n", ip); */
315
316    return NULL;
317}
318
319static struct peer *peers_get_next_free(void)
320{
321    if(peers_alloc < MAX_PEERS) {
322        return &peers[peers_alloc++];
323    } else {
324        return NULL;
325    }
326}
327
328static struct packet *get_tx_packet(void)
329{
330    struct packet *p = &tx_packets[tx_idx];
331
332    // Busy-wait until packet not in flight
333    while(p->len != 0) {
334        /* printf("Pipeline stalled! tx_packets_available = %zd\n", tx_packets_available); */
335        handle_free_tx_slot_fn_ptr();
336        /* if(!handle_free_tx_slot_fn_ptr()) { */
337        /*     printf("No packets could be freed!\n"); */
338        /* } */
339    }
340
341    /* tx_packets_available--; */
342
343    tx_idx = (tx_idx + 1) % MAX_PACKETS;
344    return p;
345}
346
347void process_received_packet(struct driver_rx_buffer *buffer, size_t count,
348                             uint64_t flags)
349{
350
351    struct packet *p = buffer->opaque;
352    assert(p != NULL);
353    assert(count == 1);
354    p->len = buffer->len;
355
356    /* printf("Incoming packet\n"); */
357    /* printf("Got %p from driver\n", p); */
358
359    assert(p >= rx_packets && p < &rx_packets[MAX_PACKETS]);
360
361    // Drop packets with invalid checksums
362    if(flags & NETIF_RXFLAG_IPCHECKSUM) {
363        if(!(flags & NETIF_RXFLAG_IPCHECKSUM_GOOD)) {
364            goto out;
365        }
366    }
367
368    if(flags & NETIF_RXFLAG_L4CHECKSUM) {
369        if(!(flags & NETIF_RXFLAG_L4CHECKSUM_GOOD)) {
370            goto out;
371        }
372    }
373
374    struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
375    switch (htons(ethhdr->type)) {
376    case ETHTYPE_ARP:
377        {
378            struct etharp_hdr *arphdr = (struct etharp_hdr *)(p->payload + SIZEOF_ETH_HDR);
379            uint32_t dipaddr = (arphdr->dipaddr.addrw[1] << 16) | arphdr->dipaddr.addrw[0];
380
381            /* printf("%d: ARP request, dip = %x\n", disp_get_core_id(), dipaddr); */
382
383            if(htons(arphdr->opcode) == ARP_REQUEST &&
384               dipaddr == arranet_myip) {
385                // Send reply
386                struct packet outp;
387		// XXX: Static payload! Need to lock if multithreaded!
388                static uint8_t payload[PACKET_SIZE];
389                struct eth_hdr *myeth = (struct eth_hdr *)payload;
390                struct etharp_hdr *myarp = (struct etharp_hdr *)(payload + SIZEOF_ETH_HDR);
391
392                /* printf("%d: ARP request for us!\n", disp_get_core_id()); */
393
394                // ETH header
395                memcpy(&myeth->dest, &arphdr->shwaddr, ETHARP_HWADDR_LEN);
396                memcpy(&myeth->src, arranet_mymac, ETHARP_HWADDR_LEN);
397                myeth->type = htons(ETHTYPE_ARP);
398
399                // ARP header
400                myarp->hwtype = htons(1);
401                myarp->proto = htons(ETHTYPE_IP);
402                myarp->hwlen = 6;
403                myarp->protolen = 4;
404                myarp->opcode = htons(ARP_REPLY);
405                memcpy(&myarp->shwaddr, arranet_mymac, ETHARP_HWADDR_LEN);
406                memcpy(&myarp->sipaddr, &arphdr->dipaddr, sizeof(myarp->sipaddr));
407                memcpy(&myarp->dhwaddr, &arphdr->shwaddr, ETHARP_HWADDR_LEN);
408                memcpy(&myarp->dipaddr, &arphdr->sipaddr, sizeof(myarp->dipaddr));
409
410                outp.payload = payload;
411                outp.len = SIZEOF_ETHARP_PACKET;
412                /* outp.len = p->len; */
413                outp.next = NULL;
414                outp.flags = 0;
415                outp.opaque = NULL;
416
417                packet_output(&outp);
418		static int arp_count = 0;
419		arp_count++;
420		if(arp_count > 100) {
421		  printf("High ARP count!\n");
422		}
423                while(!e1000n_queue_empty()) thread_yield();
424            }
425        }
426        break;
427
428    case ETHTYPE_IP:
429        {
430            struct ip_hdr *iphdr = (struct ip_hdr *)(p->payload + SIZEOF_ETH_HDR);
431
432            printf("%d: Is an IP packet, type %x\n", disp_get_core_id(), IPH_PROTO(iphdr));
433
434            // Has to be UDP or TCP
435            if(IPH_PROTO(iphdr) != IP_PROTO_UDP && IPH_PROTO(iphdr) != IP_PROTO_TCP) {
436                goto out;
437            }
438
439            // XXX: Filter for our IP
440            if(iphdr->dest.addr != arranet_myip) {
441                goto out;
442            }
443
444            if(IPH_PROTO(iphdr) == IP_PROTO_UDP) {
445                struct udp_hdr *udphdr = (struct udp_hdr *)(p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
446                uint8_t *payload = p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr);
447
448                printf("Got UDP packet, dest IP %x, dest port %u\n",
449                       htonl(iphdr->dest.addr), htons(udphdr->dest));
450
451                // XXX: Filter for UDP ports 1234
452                // TODO: Done in hardware soon
453                if(htons(udphdr->dest) != 1234) {
454                    goto out;
455                }
456
457                printf("payload '%s'\n", payload);
458
459                struct packet *outp = get_tx_packet();
460                struct eth_hdr *myeth = (struct eth_hdr *)outp->payload;
461                struct ip_hdr *myip = (struct ip_hdr *)(outp->payload + SIZEOF_ETH_HDR);
462                struct udp_hdr *myudp = (struct udp_hdr *)(outp->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
463                uint8_t *mypayload = outp->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr);
464
465                // ETH header
466                memcpy(&myeth->dest, &ethhdr->src, ETHARP_HWADDR_LEN);
467                memcpy(&myeth->src, &ethhdr->dest, ETHARP_HWADDR_LEN);
468                myeth->type = htons(ETHTYPE_IP);
469
470                // IP header
471                memcpy(myip, iphdr, sizeof(struct ip_hdr));
472                memcpy(&myip->src, &iphdr->dest, sizeof(ip_addr_p_t));
473                memcpy(&myip->dest, &iphdr->src, sizeof(ip_addr_p_t));
474
475                // UDP header
476                memcpy(myudp, udphdr, sizeof(struct udp_hdr));
477                myudp->src = udphdr->dest;
478                myudp->dest = udphdr->src;
479
480                // Payload
481                memcpy(mypayload, payload, htons(udphdr->len) - 8);
482
483                outp->len = p->len;
484                outp->next = NULL;
485                outp->flags = 0;
486                packet_output(outp);
487            }
488
489            // ARP management
490            if(peers_get_from_ip(iphdr->src.addr) == NULL) {
491                struct peer *newpeer = peers_get_next_free();
492                assert(p != NULL);
493                newpeer->ip = iphdr->src.addr;
494                memcpy(&newpeer->mac.addr, &ethhdr->src.addr, ETHARP_HWADDR_LEN);
495            }
496#if 0
497            // Push packets up - signal channel
498            assert(inpkt == NULL);
499            inpkt = p;
500            if (waitset_chan_is_registered(&recv_chanstate)) {
501                errval_t err = waitset_chan_trigger(&recv_chanstate);
502                assert(err_is_ok(err));
503            }
504
505            // Return here, packet is in flight to user-space
506            return;
507#endif
508        }
509        break;
510
511    default:
512        break;
513    }
514
515 out:
516    {
517        //now we have consumed the preregistered pbuf containing a received packet
518        //which was processed in this function. Therefore we have to register a new
519        //free buffer for receiving packets.
520        errval_t err = rx_register_buffer_fn_ptr(p->pa, p->payload, p);
521        assert(err_is_ok(err));
522    }
523}
524
525bool handle_tx_done(void *opaque)
526{
527    struct packet *p = opaque;
528    if(p >= tx_packets && p < &tx_packets[MAX_PACKETS]) {
529        /* printf("Packet from TX ring, marking available\n"); */
530        // Mark packet as available, if coming from TX packet array
531        p->len = 0;
532        /* tx_packets_available++; */
533#ifndef SENDMSG_WITH_COPY
534    } else {
535        if(opaque != NULL && arranet_tx_done_callback != NULL) {
536            /* printf("Packet from app, handing up\n"); */
537            arranet_tx_done_callback(opaque);
538            /* } else { */
539        /*     if(opaque == NULL) { */
540        /*         printf("NULL packet\n"); */
541        /*     } */
542    }
543#endif
544    }
545
546    return true;
547}
548
549/* allocate a single frame, mapping it into our vspace with given attributes */
550static void *alloc_map_frame(vregion_flags_t attr, size_t size, struct capref *retcap)
551{
552    struct capref frame;
553    errval_t r;
554
555    r = frame_alloc(&frame, size, NULL);
556    assert(err_is_ok(r));
557    void *va;
558    r = vspace_map_one_frame_attr(&va, size, frame, attr,
559                                  NULL, NULL);
560    if (err_is_fail(r)) {
561        DEBUG_ERR(r, "vspace_map_one_frame failed");
562        return NULL;
563    }
564
565    if (retcap != NULL) {
566        *retcap = frame;
567    }
568
569    return va;
570}
571
572static const char *eat_opts[] = {
573    "function=", "interrupts=", "queue=", "msix=", "vf=", "device=", "bus=", "use_vtd=",
574    NULL
575};
576
577int main(int argc, char *argv[])
578{
579    uint8_t mac[6];
580
581    errval_t err = skb_client_connect();
582    assert(err_is_ok(err));
583
584    err = skb_execute_query("vtd_enabled(0,C), write(vtd_coherency(C)).");
585    if (err_is_ok(err)) {
586        use_vtd = 1;
587        for(int i = 0; i < argc; i++) {
588            if(!strncmp(argv[i], "use_vtd=", strlen("use_vtd=") - 1)) {
589                use_vtd = !!atol(argv[i] + strlen("use_vtd="));
590                break;
591            }
592        }
593        err = skb_read_output("vtd_coherency(%d)", &vtd_coherency);
594        assert(err_is_ok(err));
595    }
596
597    if (use_vtd) {
598        err = connect_to_acpi();
599        assert(err_is_ok(err));
600        err = vtd_create_domain(cap_vroot);
601        assert(err_is_ok(err));
602        err = vtd_domain_add_device(0, 13, 16, 1, cap_vroot);
603        assert(err_is_ok(err));
604    }
605
606    e1000n_driver_init(argc, argv);
607
608    ether_get_mac_address_ptr(mac);
609    printf("Arranet MAC address %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
610           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
611
612    struct capref frame;
613    uint8_t *ram_base = alloc_map_frame(VREGION_FLAGS_READ_WRITE,
614                                        MAX_PACKETS * PACKET_SIZE + 4096, &frame);
615    assert(ram_base != NULL);
616
617    struct frame_identity id;
618    err = frame_identify(frame, &id);
619    assert(err_is_ok(err));
620
621    rx_pbase = id.base;
622    rx_vbase = (genvaddr_t)ram_base;
623
624    // Add buffers to RX ring for packet reception
625    for(int i = 0; i < MAX_PACKETS; i++) {
626        struct packet *p = &rx_packets[i];
627
628        // XXX: Use this for recvfrom_arranet to get alignment
629        /* p->payload = ram_base + (i * PACKET_SIZE) + 6; */
630        /* p->pa = id.base + (i * PACKET_SIZE) + 6; */
631        p->payload = ram_base + (i * PACKET_SIZE);
632        p->pa = id.base + (i * PACKET_SIZE);
633        p->len = PACKET_SIZE;
634        p->flags = 0;
635
636        err = rx_register_buffer_fn_ptr(p->pa, p->payload, p);
637        assert(err_is_ok(err));
638    }
639
640    // Allocate TX buffers (to have them all backed by one frame)
641    uint8_t *tx_bufs = alloc_map_frame(VREGION_FLAGS_READ_WRITE,
642                                       MAX_PACKETS * PACKET_SIZE, &frame);
643    assert(tx_bufs != NULL);
644
645    err = frame_identify(frame, &id);
646    assert(err_is_ok(err));
647    tx_pbase = id.base;
648    tx_vbase = (genvaddr_t)tx_bufs;
649
650    // Initialize TX packet descriptors
651    for(int i = 0; i < MAX_PACKETS; i++) {
652        /* tx_packets[i].payload = tx_bufs[i]; */
653        tx_packets[i].payload = tx_bufs + (i * PACKET_SIZE);
654    }
655
656    if (!vtd_coherency) {// For the UDP echo server
657        sys_debug_flush_cache();
658    }
659
660    // Determine my static IP address
661    for(int i = 0; i < sizeof(ip_config) / sizeof(struct mac2ip); i++) {
662        struct mac2ip *e = &ip_config[i];
663        if(!memcmp(mac, e->mac, ETHARP_HWADDR_LEN)) {
664            arranet_myip = htonl(e->ip);
665            memcpy(arranet_mymac, e->mac, ETHARP_HWADDR_LEN);
666            break;
667        }
668    }
669
670    if(arranet_myip == 0) {
671        USER_PANIC("Arranet: No static IP config for this MAC address!\n");
672    }
673
674    /***** Initialize IP/Ethernet packet header template *****/
675    {
676        struct pkt_ip_headers *p = &packet_ip_header;
677
678        // Initialize Ethernet header
679        memcpy(&p->eth.src, mac, ETHARP_HWADDR_LEN);
680        p->eth.type = htons(ETHTYPE_IP);
681
682        // Initialize IP header
683        p->ip._v_hl = 69;
684        p->ip._tos = 0;
685        p->ip._id = htons(3);
686        p->ip._offset = 0;
687        p->ip._ttl = 0xff;
688        p->ip._proto = 0;
689        p->ip._chksum = 0;
690        p->ip.src.addr = arranet_myip;
691    }
692
693    /***** Initialize UDP/IP/Ethernet packet header template *****/
694    {
695        struct pkt_udp_headers *p = &packet_udp_header;
696
697        // Initialize Ethernet header
698        memcpy(&p->eth.src, mac, ETHARP_HWADDR_LEN);
699        p->eth.type = htons(ETHTYPE_IP);
700
701        // Initialize IP header
702        p->ip._v_hl = 69;
703        p->ip._tos = 0;
704        p->ip._id = htons(3);
705        p->ip._offset = 0;
706        p->ip._ttl = 0xff;
707        p->ip._proto = IP_PROTO_UDP;
708        p->ip._chksum = 0;
709        p->ip.src.addr = arranet_myip;
710
711        // Initialize UDP header
712        p->udp.chksum = 0;
713    }
714
715    /***** Initialize TCP/IP/Ethernet packet header template *****/
716    {
717        struct pkt_tcp_headers *p = &packet_tcp_header;
718
719        // Initialize Ethernet header
720        memcpy(&p->eth.src, mac, ETHARP_HWADDR_LEN);
721        p->eth.type = htons(ETHTYPE_IP);
722
723        // Initialize IP header
724        p->ip._v_hl = 69;
725        p->ip._tos = 0;
726        p->ip._id = htons(3);
727        p->ip._offset = 0;
728        p->ip._ttl = 0xff;
729        p->ip._proto = IP_PROTO_TCP;
730        p->ip._chksum = 0;
731        p->ip.src.addr = arranet_myip;
732
733        // Initialize TCP header
734        p->tcp.chksum = 0;
735        p->tcp.wnd = 65535;
736    }
737
738    /***** Eat driver-specific options *****/
739    static char *new_argv[ARG_MAX];
740    int new_argc = 0;
741    for(int i = 0; i < argc; i++) {
742        int j;
743
744        for(j = 0; eat_opts[j] != NULL; j++) {
745            if(!strncmp(argv[i], eat_opts[j], strlen(eat_opts[j]) - 1)) {
746                // Option matches -- delete!
747                break;
748            }
749        }
750
751        if(eat_opts[j] == NULL) {
752            // Option doesn't match -- keep!
753            new_argv[new_argc++] = argv[i];
754        }
755    }
756
757    argc = new_argc;
758    argv = new_argv;
759
760    printf("e10ktest initialized.\n");
761
762    for(;;) {
763        arranet_polling_loop();
764        //        e1000n_polling_loop(get_default_waitset());
765    }
766}
767