224 lines
5.0 KiB
C
224 lines
5.0 KiB
C
/*
|
|
* 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 <aos/simpleslab.h>
|
|
#include <aos/ump_chan.h>
|
|
#include <aos/ump_net.h>
|
|
#include <collections/hash_table.h>
|
|
|
|
#include <netutil/types.h>
|
|
#include <netutil/etharp.h>
|
|
#include <netutil/ip.h>
|
|
#include <netutil/udp.h>
|
|
|
|
// 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;
|
|
struct icmp_echo_hdr *icmp_echo_hdr;
|
|
struct eth_hdr *eth_hdr;
|
|
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_
|