/* * Copyright (c) 2019, 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. */ #ifndef ENET_H_ #define ENET_H_ #include #include #include #include #include #include #include #include // enable verbose debug logs //#define ENET_DEBUG_OPTION 1 // enable warnings when packets are dropped, and other unusual events happen #define ENET_WARN_OPTION 1 #if defined(ENET_DEBUG_OPTION) #define ENET_DEBUG(x...) debug_printf("[enet] " x); #else #define ENET_DEBUG(fmt, ...) ((void)0) #endif #if defined(ENET_WARN_OPTION) #define ENET_WARN(x...) debug_printf("[enet] WARN: " x); #else #define ENET_WARN(fmt, ...) ((void)0) #endif #define ENET_PROMISC #define TX_RING_SIZE 512 #define ENET_RX_FRSIZE 2048 #define ENET_RX_PAGES 256 #define ENET_MAX_PKT_SIZE 1536 #define ENET_MAX_BUF_SIZE 2048 #define RX_RING_SIZE (BASE_PAGE_SIZE / ENET_RX_FRSIZE) * ENET_RX_PAGES #define ENET_RX_EMPTY 0x8000 #define ENET_SC_WRAP ((ushort)0x2000) #define ENET_RX_intr ((ushort)0x1000) #define ENET_RX_LAST ((ushort) 0x0800) #define ENET_RX_FIRST ((ushort) 0x0400) #define ENET_RX_MISS ((ushort) 0x0100) #define ENET_RX_LG ((ushort) 0x0020) #define ENET_RX_NO ((ushort) 0x0010) #define ENET_RX_SH ((ushort) 0x0008) #define ENET_RX_CR ((ushort) 0x0004) #define ENET_RX_OV ((ushort) 0x0002) #define ENET_RX_CL ((ushort) 0x0001) #define ENET_RX_STATS ((ushort) 0x013f) #define ENET_TX_READY 0x8000 #define ENET_TX_WRAP 0x2000 #define ENET_TX_LAST 0x0800 #define ENET_TX_CRC 0x0400 struct region_entry { uint32_t rid; struct dmem mem; struct region_entry* next; }; struct enet_queue { struct devq q; size_t size; // stop and wake threashold uint16_t stop_th; uint16_t wake_th; char* tso_hdr; struct capref regs; struct dmem desc_mem; enet_t* d; // hd + tail size_t head; size_t tail; // alignment size_t align; // Descriptor + Cleanq enet_bufdesc_array_t *ring; struct devq_buf *ring_bufs; struct region_entry* regions; }; typedef void (*tx_alloc_callback_t)(void *cb_arg, struct devq_buf *buf, void *vaddr); struct tx_alloc_queue_entry { tx_alloc_callback_t cb; void *cb_arg; struct tx_alloc_queue_entry *next; }; #define ARP_TX_QUEUE_LEN 64 STATIC_ASSERT((ARP_TX_QUEUE_LEN & (ARP_TX_QUEUE_LEN - 1)) == 0, "Must be power of 2"); struct arp_tx_queue_entry { struct tx_alloc_queue_entry tx_entry; uint64_t eth_dst; uint32_t ip_dst; }; struct arp_state { struct arp_tx_queue_entry tx_queue[ARP_TX_QUEUE_LEN]; size_t tx_queue_len; size_t tx_queue_tail; collections_hash_table* table; }; struct ip_state { uint16_t next_id; }; struct udp_state { collections_hash_table* listen_table; uint16_t next_ephemeral_port; }; struct ump_client; struct ump_reply_buf { struct ump_send_queue_entry ump_entry; struct ump_net_in_header ump_header; struct ump_client *client; }; struct ump_client { struct ump_send_chan *send_chan; struct ump_recv_chan *recv_chan; struct tx_alloc_queue_entry tx_entry; struct devq_buf tx_buf; struct ip_hdr *tx_ip_hdr; // If ump_reply_slab becomes empty, this is set to true and // UMP receiving is blocked. bool blocked_on_reply_slab; struct simpleslab_allocator ump_reply_slab; uint8_t ump_reply_slab_buf[sizeof(struct ump_reply_buf) * 128]; }; struct icmp_echo_reply_meta { struct devq_buf rx_buf; struct tx_alloc_queue_entry tx_entry; const struct icmp_echo_hdr *icmp_echo_hdr; const struct eth_hdr *eth_hdr; const struct ip_hdr *ip_hdr; }; struct udp_recv { struct devq_buf rx_buf; struct ump_send_queue_entry ump_entry; struct ump_net_in_header ump_header; }; // union to obtain max required size union rx_meta_slab_data { struct icmp_echo_reply_meta icmp_echo_reply_meta; struct udp_recv udp_recv; }; struct enet_driver_state { struct bfdriver_instance *bfi; struct capref regs; lvaddr_t d_vaddr; struct enet_queue* rxq; struct enet_queue* txq; enet_t* d; uint64_t mac; uint32_t phy_id; struct capref rx_mem; struct capref tx_mem; regionid_t tx_rid; int tx_init_i; ip_addr_t my_ip; int net_bits; ip_addr_t net_mask; struct tx_alloc_queue_entry *tx_alloc_queue_head; struct tx_alloc_queue_entry *tx_alloc_queue_tail; // There are exactly as many of these blocks as there are RX buffers. // You can allocate one for as long as you hold an RX buffer. struct simpleslab_allocator rx_meta_slab; uint8_t rx_meta_slab_buf[sizeof(union rx_meta_slab_data) * RX_RING_SIZE]; struct arp_state arp; struct ip_state ip; struct udp_state udp; }; #define ENET_HASH_BITS 6 #define ENET_CRC32_POLY 0xEDB88320 void enet_loop (void); #endif // ndef ENET_H_