#define TRACE_ONLY_SUB_BNET 1
#endif // CONFIG_TRACE && NETWORK_STACK_BENCHMARK
-#if CONFIG_TRACE
-#define TRACE_ONLY_SUB_NNET 1
-#endif
+#if CONFIG_TRACE && NETWORK_LLSTACK_TRACE
+#define TRACE_ONLY_LLNET 1
+#endif // CONFIG_TRACE && NETWORK_LLSTACK_TRACE
+
+
/**
- * \brief Constants for trace subsystems and events.
- *
- * Please try and keep this under control. Each subsystem should be
- * preceeded by two blank lines and followed by its events. If events
- * within a subsystem need to be grouped with whitespace then use a
- * single blank line.
- *
+ * The constants for the subsystems and events are generated from the file
+ * trace_definitions/trace_defs.pleco that can be included after compiling with
+ * #include <trace_definitions/trace_defs.h>
+ * .
*/
- #define TRACE_SUBSYS_KERNEL 0xFFFF
- #define TRACE_EVENT_CSWITCH 0xCCCC
- #define TRACE_EVENT_BZERO 0xB0
- #define TRACE_EVENT_TIMER 0x1
- #define TRACE_EVENT_TIMER_SYNC 0x2
-
- #define TRACE_EVENT_SCHED_MAKE_RUNNABLE 0xED00
- #define TRACE_EVENT_SCHED_REMOVE 0xED01
- #define TRACE_EVENT_SCHED_YIELD 0xED02
- #define TRACE_EVENT_SCHED_SCHEDULE 0xED03
- #define TRACE_EVENT_SCHED_CURRENT 0xED04
-
- #define TRACE_SUBSYS_THREADS 0xEEEE
-
- #define TRACE_EVENT_BARRIER_ENTER 0x0100
- #define TRACE_EVENT_BARRIER_LEAVE 0x0101
-
- #define TRACE_EVENT_MUTEX_LOCK_ENTER 0x0200
- #define TRACE_EVENT_MUTEX_LOCK_LEAVE 0x0201
- #define TRACE_EVENT_MUTEX_LOCK_NESTED_ENTER 0x0202
- #define TRACE_EVENT_MUTEX_LOCK_NESTED_LEAVE 0x0203
- #define TRACE_EVENT_MUTEX_TRYLOCK 0x0204
- #define TRACE_EVENT_MUTEX_UNLOCK 0x0205
-
- #define TRACE_EVENT_COND_WAIT_ENTER 0x0300
- #define TRACE_EVENT_COND_WAIT_LEAVE 0x0301
- #define TRACE_EVENT_COND_SIGNAL 0x0302
- #define TRACE_EVENT_COND_BROADCAST 0x0303
-
- #define TRACE_EVENT_SEM_WAIT_ENTER 0x0400
- #define TRACE_EVENT_SEM_WAIT_LEAVE 0x0401
- #define TRACE_EVENT_SEM_TRYWAIT 0x0402
- #define TRACE_EVENT_SEM_POST 0x0403
-
-
- #define TRACE_SUBSYS_MEMSERV 0xA000
- #define TRACE_EVENT_ALLOC 0x0001
-
-
- #define TRACE_SUBSYS_MONITOR 0xB000
- #define TRACE_EVENT_SPAN0 0x0000
- #define TRACE_EVENT_SPAN1 0x0001
- #define TRACE_EVENT_SPAN 0x0002
- #define TRACE_EVENT_PCREQ 0x0003
- #define TRACE_EVENT_PCREPLY 0x0004
- #define TRACE_EVENT_PCREQ_INTER 0x0005
- #define TRACE_EVENT_PCREPLY_INTER 0x0006
- #define TRACE_EVENT_URPC_BLOCK 0x0007
- #define TRACE_EVENT_URPC_UNBLOCK 0x0008
- #define TRACE_EVENT_REMOTE_CAP_RETYPE 0x0009
- #define TRACE_EVENT_REMOTE_CAP_RETYPE_RETRY 0x0010
- #define TRACE_EVENT_REMOTE_CAP_RETYPE_MSG 0x0011
- #define TRACE_EVENT_REMOTE_CAP_RETYPE_END 0x0012
- #define TRACE_EVENT_POLLING 0xBBBB
-
-
- #define TRACE_SUBSYS_CHIPS 0xC000
- #define TRACE_EVENT_CHIPS_LISTENCB 0x0001
-
-
- #define TRACE_SUBSYS_BFLIB 0xBFBF
-
-
- #define TRACE_SUBSYS_TWEED 0x2000
- #define TRACE_EVENT_TWEED_START 0x0000
- #define TRACE_EVENT_TWEED_END 0x0001
- #define TRACE_EVENT_STEAL 0x0002
- #define TRACE_EVENT_STEAL_END 0x0003
- #define TRACE_EVENT_WAIT 0x0004
- #define TRACE_EVENT_WAIT_END 0x0005
- #define TRACE_EVENT_LOCKING 0x0006
- #define TRACE_EVENT_LOCKING_END 0x0007
-
-
- #define TRACE_SUBSYS_ROUTE 0x3000
- #define TRACE_EVENT_BCAST_WITH_CCAST_SEND 0x0001
- #define TRACE_EVENT_BCAST_WITH_CCAST 0x0002
- #define TRACE_EVENT_RECV_BCAST_WITH_CCAST 0x0003
- #define TRACE_EVENT_RECV_CCAST 0x0004
- #define TRACE_EVENT_ROUTE_BENCH_START 0x0005
- #define TRACE_EVENT_ROUTE_BENCH_STOP 0x0006
- #define TRACE_EVENT_ROUTE_SEND_PING 0x0007
- #define TRACE_EVENT_ROUTE_SEND_PONG 0x0008
- #define TRACE_EVENT_ROUTE_RECV_PING 0x0009
- #define TRACE_EVENT_ROUTE_RECV_PONG 0x000A
- #define TRACE_EVENT_ROUTE_POLL 0x000B
-
-
- #define TRACE_SUBSYS_BENCH 0x1234
- #define TRACE_EVENT_PCBENCH 0x0000
- #define TRACE_EVENT_RXPING 0x0001
- #define TRACE_EVENT_RXPONG 0x0002
-
-
- #define TRACE_SUBSYS_BOMP 0x4000
- #define TRACE_EVENT_BOMP_START 0x0001
- #define TRACE_EVENT_BOMP_STOP 0x0002
- #define TRACE_EVENT_BOMP_ITER 0x0003
-
-
- #define TRACE_SUBSYS_BARRIERS 0x5000
- #define TRACE_EVENT_BARRIERS_START 0X0001
- #define TRACE_EVENT_BARRIERS_STOP 0X0002
- #define TRACE_EVENT_BARRIERS_BARRIER_WAIT 0X0003
- #define TRACE_EVENT_BARRIERS_CENTRAL_REQ 0X0004
- #define TRACE_EVENT_BARRIERS_CENTRAL_REP 0X0005
- #define TRACE_EVENT_BARRIERS_TREE_REQ 0X0006
- #define TRACE_EVENT_BARRIERS_TREE_REP 0X0007
- #define TRACE_EVENT_BARRIERS_DIST 0X0008
- #define TRACE_EVENT_BARRIERS_SEND 0X0009
- #define TRACE_EVENT_BARRIERS_POLL1 0X000A
- #define TRACE_EVENT_BARRIERS_POLL2 0X000B
- #define TRACE_EVENT_BARRIERS_HEAP_REQ 0X000C
- #define TRACE_EVENT_BARRIERS_HEAP_REP 0X000D
- #define TRACE_EVENT_BARRIERS_SEQ_BCAST_REQ 0X000E
- #define TRACE_EVENT_BARRIERS_SEQ_BCAST_RECV 0X000F
- #define TRACE_EVENT_BARRIERS_TREE_BCAST_REQ 0X0010
- #define TRACE_EVENT_BARRIERS_TREE_BCAST_RECV 0X0011
-
- /* Following constants are used in network subsystem. */
- #define TRACE_SUBSYS_NET 0x6000
- #define TRACE_EVENT_NET_START 0X0001
- #define TRACE_EVENT_NET_STOP 0X0002
- #define TRACE_EVENT_NET_NI_AI 0X0012 /* added, 0 */
- #define TRACE_EVENT_NET_NI_I 0X0010 /* added, 0 */
- #define TRACE_EVENT_NET_NI_A 0X0003 /* added, pkt data location */
- #define TRACE_EVENT_NET_NI_FILTER_FRAG 0X0018 /* added, pkt data location */
- #define TRACE_EVENT_NET_NI_FILTER_EX_1 0X0015 /* added, pkt data location */
- #define TRACE_EVENT_NET_NI_ARP 0X0011 /* added, pkt data location */
- #define TRACE_EVENT_NET_NI_FILTER_EX_2 0X0016 /* added, pkt data location */
- #define TRACE_EVENT_NET_NI_PKT_CPY_1 0X0019 /* added, pkt data location */
- #define TRACE_EVENT_NET_NI_PKT_CPY_2 0X001A /* added, pkt data location */
- #define TRACE_EVENT_NET_NI_PKT_CPY_3 0X001B /* added, pkt data location */
- #define TRACE_EVENT_NET_NI_PKT_CPY_4 0X001C /* added, pkt data location */
-
- #define TRACE_EVENT_NET_NI_PKT_CPY 0X0017 /* added, pkt data location */
- #define TRACE_EVENT_NET_NI_P 0X0004 /* added, pbuf_id */
- #define TRACE_EVENT_NET_NI_S 0X0005 /* added, pbuf_id */
- #define TRACE_EVENT_NET_AI_A 0X0006 /* added, pbuf_id */
- #define TRACE_EVENT_NET_AI_P 0X0007 /* added, pbuf_addr */
- #define TRACE_EVENT_NET_AO_C 0X0008 /* added, pbuf_addr */
- #define TRACE_EVENT_NET_AO_Q 0X0009 /* added, pbuf_addr */
- #define TRACE_EVENT_NET_AO_S 0X000A /* added, pbuf_addr (as client_data ) */
- #define TRACE_EVENT_NET_NO_A 0X000B /* added, client_data (pbuf_address in lwip) */
- #define TRACE_EVENT_NET_NO_S 0X000C /* added, e1000n.c client_data (pbuf_address in lwip) */
-
- /* FIXME: Add the timings of when does NIC gets TX_done */
- #define TRACE_EVENT_NET_NO_TXD 0X0013 /* yet to add */
- #define TRACE_EVENT_NET_AIR_R 0x000E /* added, pbuf_addr (TX DONE in app) */
-
- /* Response flow */
- #define TRACE_EVENT_NET_AOR_S 0x000D /* added, pbuf_id ( register_pbuf from APP)*/
- #define TRACE_EVENT_NET_NIR_REG_PBUF 0x0014 /* commented pbuf_id ( register_pbuf in NIC)*/
-
- #define TRACE_SUBSYS_MULTIHOP 0x7000
- #define TRACE_EVENT_MULTIHOP_BENCH_START 0x0001
- #define TRACE_EVENT_MULTIHOP_BENCH_STOP 0x0002
- #define TRACE_EVENT_MULTIHOP_MESSAGE_SEND 0x0003
- #define TRACE_EVENT_MULTIHOP_MESSAGE_RECEIVE 0x0004
-
- /* Following constants are used in network benchmark. */
- #define TRACE_SUBSYS_BNET 0x8000
- #define TRACE_EVENT_BNET_START 0x0001
- #define TRACE_EVENT_BNET_STOP 0x0002
- #define TRACE_EVENT_BNET_DRV_SEE 0x0003
- #define TRACE_EVENT_BNET_APP_SEE 0x0004
- #define TRACE_EVENT_BNET_DRV_INT 0x0005
- #define TRACE_EVENT_BNET_DRV_POLL 0x0006
- #define TRACE_EVENT_BNET_YIELD 0x0007
- #define TRACE_EVENT_BNET_I 0x0008
-
-
- /* Following constans are used for profiling modified stack */
- #define TRACE_SUBSYS_NNET 0x9000
- #define TRACE_EVENT_NNET_START 0x0001
- #define TRACE_EVENT_NNET_STOP 0x0002
- #define TRACE_EVENT_NNET_RXDRVSEE 0x0003 // Driver saw pkg (RX)
- #define TRACE_EVENT_NNET_RXESVSEE 0x0004 // Ethersrv saw pkg
- #define TRACE_EVENT_NNET_RXESVFRGDONE 0x0005 // Ethersrv checked frag
- #define TRACE_EVENT_NNET_RXESVAPPFDONE 0x0006 // Ethersrv app filtered
- #define TRACE_EVENT_NNET_RXESVAPPCSTART 0x0007 // Ethersrv app c2u started
- #define TRACE_EVENT_NNET_RXESVCOPIED 0x0008 // Ethersrv copied pkg
- #define TRACE_EVENT_NNET_RXESVSPPDONE 0x000D // Ethersrv spp produce done
- #define TRACE_EVENT_NNET_RXESVAPPNOTIF 0x0009 // Ethersrv app notify
- #define TRACE_EVENT_NNET_RXLWIINCOM 0x000A // LWIP handle_incoming_
- #define TRACE_EVENT_NNET_RXLWIRECH 0x000B // LWIP call rec_handler
- #define TRACE_EVENT_NNET_RXAPPRCV 0x000C // APP received
-
- #define TRACE_EVENT_NNET_TXAPPSNT 0x0020 // APP sent
- #define TRACE_EVENT_NNET_TXLWISEE 0x0021 // LWIP idc_send_packet
- #define TRACE_EVENT_NNET_TXLWIBFFENCE 0x0029 // LWIP before mfence
- #define TRACE_EVENT_NNET_TXLWIAFFENCE 0x002A // LWIP after mfence
- #define TRACE_EVENT_NNET_TXLWIFLUSHED 0x002B // LWIP payload flushed
- #define TRACE_EVENT_NNET_TXLWIBDESC 0x002C // LWIP bufferdesc fetched
- #define TRACE_EVENT_NNET_TXLWISPPSND 0x0022 // LWIP spp produced
- #define TRACE_EVENT_NNET_TXLWISPPIDX 0x0023 // LWIP update spp index
- #define TRACE_EVENT_NNET_TXLWITXWORK 0x002D // LWIP pending TX work
- #define TRACE_EVENT_NNET_TXLWINOTIF 0x0024 // LWIP notify driver
- #define TRACE_EVENT_NNET_TXESVNOTIF 0x0025 // Ethersrv notify recieved
- #define TRACE_EVENT_NNET_TXESVSPOW 0x002E // Ethersrv send_pkt_on_w..
- #define TRACE_EVENT_NNET_TXESVSSPOW 0x0026 // Ethersrv send_sng_pkt..
- #define TRACE_EVENT_NNET_TXDRVADD 0x0027 // Driver add pkg (TX)
- #define TRACE_EVENT_NNET_TXDRVSEE 0x0028 // Driver saw pkg done (TX)
- #define TRACE_EVENT_NNET_TX_TCP_WRITE 0x0030 // tcp_write done
- #define TRACE_EVENT_NNET_TX_TCP_OUTPUT 0x0031 // tcp_output done
- #define TRACE_EVENT_NNET_TX_TCP_RECV 0x0032 // tcp_recved done
- #define TRACE_EVENT_NNET_TX_TCP_FREE 0x0033 // tx pbuf freed
- #define TRACE_EVENT_NNET_TX_MEMP 0x0034 // tx pbuf memp start
- #define TRACE_EVENT_NNET_TX_MEMP_D 0x0035 // tx pbuf memp done
+ #include <trace_definitions/trace_defs.h>
+
+/* Constant for low-level networking trace */
+#define TRACE_SUBSYS_LLNET 0xD000
+#define TRACE_EVENT_LLNET_START 0x0001
+#define TRACE_EVENT_LLNET_STOP 0x0002
+#define TRACE_EVENT_LLNET_IRQ 0x0003
+#define TRACE_EVENT_LLNET_LMPDISP 0x0004
+
+#define TRACE_EVENT_LLNET_DRVIRQ 0x0010
+#define TRACE_EVENT_LLNET_DRVRX 0x0011
+#define TRACE_EVENT_LLNET_DRVTXADD 0x0012
+#define TRACE_EVENT_LLNET_DRVTXDONE 0x0013
+
+#define TRACE_EVENT_LLNET_LWIPPBA1 0x0020
+#define TRACE_EVENT_LLNET_LWIPPBA2 0x0021
+#define TRACE_EVENT_LLNET_LWIPPBF1 0x0022
+#define TRACE_EVENT_LLNET_LWIPPBF2 0x0023
+#define TRACE_EVENT_LLNET_LWIPRX 0x0024
+#define TRACE_EVENT_LLNET_LWIPTX 0x0025
+
+#define TRACE_EVENT_LLNET_APPRX 0x0030
+#define TRACE_EVENT_LLNET_APPTX 0x0031
+
+
+
#define TRACE_EVENT(s,e,a) ((uint64_t)(s)<<48|(uint64_t)(e)<<32|(a))
/* XXX: this is a temp kludge. The tracing code wants to allocate a fixed buffer
#if CONFIG_TRACE && NETWORK_STACK_BENCHMARK
#define TRACE_N_BM 1
-#endif
+#endif // CONFIG_TRACE && NETWORK_STACK_BENCHMARK
+ #define MAX_ALLOWED_PKT_PER_ITERATION (0xff) // working value
+ /* Transmit and receive buffers must be multiples of 8 */
+ #define DRIVER_RECEIVE_BUFFERS (1024 * 8)
+ #define DRIVER_TRANSMIT_BUFFERS (1024 * 8)
+//#define ENABLE_DEBUGGING_E1000 1
+#ifdef ENABLE_DEBUGGING_E1000
+static bool local_debug = true;
+#define E1000N_DPRINT(x...) do{if(local_debug) printf("e1000n: " x); } while(0)
+#else
+#define E1000N_DPRINT(x...) ((void)0)
+#endif // ENABLE_DEBUGGING_E1000
- /*****************************************************************
- * Data types:
- *****************************************************************/
+ /* MTU is 1500 bytes, plus Ethernet header plus CRC. */
+ #define RX_PACKET_MAX_LEN (1500 + 14 + 4)
+ #define PACKET_SIZE_LIMIT 1073741824 /* 1 Gigabyte */
+
+ /*****************************************************************
+ * External declarations for net_queue_manager
+ *
+ ****************************************************************/
extern uint64_t interrupt_counter;
extern uint64_t total_rx_p_count;
- extern uint64_t total_interrupt_time;
extern struct client_closure *g_cl;
- extern uint64_t total_processing_time;
extern uint64_t total_rx_datasize;
- static uint8_t macaddr[6]; ///< buffers the card's MAC address upon card reset
- e1000_t d; ///< Mackerel state
- static bool user_macaddr; /// True iff the user specified the MAC address
- static bool use_interrupt = true;
-
- #define MAX_ALLOWED_PKT_PER_ITERATION (0xff) // working value
- #define DRIVER_RECEIVE_BUFFERS (1024 * 8) // Number of buffers with driver
- #define RECEIVE_BUFFER_SIZE (2048) // MAX size of ethernet packet
-
- #define DRIVER_TRANSMIT_BUFFER (1024 * 8)
-
- //transmit
+ /*****************************************************************
+ * Receive and transmit
+ *****************************************************************/
+ static e1000_rx_bsize_t receive_buffer_size = bsize_16384;
static volatile struct tx_desc *transmit_ring;
+
+// Data-structure to map sent buffer slots back to application slots
+struct pbuf_desc {
+ void *opaque;
+};
+static struct pbuf_desc pbuf_list_tx[DRIVER_TRANSMIT_BUFFER];
+//remember the tx pbufs in use
+
+//receive
static volatile union rx_desc *receive_ring;
- static uint32_t ether_transmit_index = 0, ether_transmit_bufptr = 0;
-
- /* TODO: check if these variables are used */
- static uint32_t receive_index = 0, receive_bufptr = 0;
- static uint32_t receive_free = 0;
+ static void *receive_ring_phys_addr = NULL;
+ static void *receive_ring_virt_addr = NULL;
-
+ static uint32_t receive_bufptr_index = 0;
+ static uint32_t receive_ring_index = 0;
+ static uint32_t receive_ring_free = 0;
-
+static void **receive_opaque = NULL;
+ /*****************************************************************
++
+ * e1000 states:
+ *****************************************************************/
+ static e1000_t e1000;
+ static e1000_device_t e1000_device;
+ static uint8_t mac_address[MAC_ADDRESS_LEN]; /* buffers the card's MAC address upon card reset */
+ /*****************************************************************
+ * argument states:
+ *****************************************************************/
+ static bool user_mac_address; /* True if the user specified the MAC address */
+ static bool use_interrupt = true; /* don't use card polling mode */
+ static bool use_force = false; /* don't attempt to find card force load */
/*****************************************************************
* Local states:
*****************************************************************/
- static uint64_t bus = PCI_DONT_CARE;
- static uint64_t device = PCI_DONT_CARE;
-static uint64_t minbase = -1;
-static uint64_t maxbase = -1;
-
+ static uint32_t class = PCI_CLASS_ETHERNET;
+ static uint32_t subclass = PCI_DONT_CARE;
+ static uint32_t bus = PCI_DONT_CARE;
+ static uint32_t device = PCI_DONT_CARE;
static uint32_t function = PCI_DONT_CARE;
static uint32_t deviceid = PCI_DONT_CARE;
+ static uint32_t vendor = PCI_VENDOR_INTEL;
+ static uint32_t program_interface = PCI_DONT_CARE;
+ static e1000_mac_type_t mac_type = e1000_undefined;
- /* FIXME: most probably, I don't need this. So, remove it. */
+ /*****************************************************************
+ * For use with the net_queue_manager
+ *
+ *****************************************************************/
static char *global_service_name = 0;
- static uint64_t assumed_queue_id = 0;
- static bool handle_free_TX_slot_fn(void);
+ static uint64_t assumed_queue_id = 0; /* what net queue to bind to */
+ static uint32_t ether_transmit_index = 0;
+ static uint32_t ether_transmit_bufptr_index = 0;
+
-/*
- * Structure to map sent buffer slots back to application slots
- */
-struct pbuf_desc {
- struct net_queue_manager_binding *sr; /* which application binding */
- uint64_t spp_index; /* which slot within spp */
-};
-
+ static struct pbuf_desc pbuf_list_tx[DRIVER_TRANSMIT_BUFFERS];
+
+ /*****************************************************************
+ * Print physical link status.
+ *
+ ****************************************************************/
+ static void e1000_print_link_status(e1000_device_t *dev)
+ {
+ const char *media_type = NULL;
+ e1000_status_t status;
+
+ status = e1000_status_rd(dev->device);
+ e1000_ledctl_rd(dev->device);
+
+ switch (dev->media_type) {
+ case e1000_media_type_copper:
+ media_type = "copper";
+ break;
+ case e1000_media_type_fiber:
+ media_type = "fiber";
+ break;
+ case e1000_media_type_serdes:
+ media_type = "SerDes";
+ break;
+ default:
+ media_type = "Unknown";
+ break;
+ }
+
+ if (e1000_check_link_up(dev)) {
+ const char *duplex;
+
+ if (e1000_status_fd_extract(status)) {
+ duplex = "Full";
+ } else {
+ duplex = "Half";
+ }
+
+ switch (e1000_status_speed_extract(status)) {
+ case 0x0:
+ E1000_PRINT("Media type: %s, Link speed: 10 Mb in %s duplex.\n",
+ media_type, duplex);
+ break;
+ case 0x1:
+ E1000_PRINT("Media type: %s, Link speed: 100 Mb in %s duplex.\n",
+ media_type, duplex);
+ break;
+ default:
+ E1000_PRINT("Media type: %s, Link speed: 1 Gb in %s duplex.\n",
+ media_type, duplex);
+ break;
+ }
+ } else {
+ E1000_PRINT("Media type: %s, Link down.\n", media_type);
+ }
+ }
+
+ /*****************************************************************
+ * And descriptor to receive ring
+ *
+ ****************************************************************/
+ static int add_desc(uint64_t paddr)
+ {
+ e1000_dqval_t dqval = 0;
+ union rx_desc desc;
+
+ desc.raw[0] = desc.raw[1] = 0;
+ desc.rx_read_format.buffer_address = paddr;
+
+ if (receive_ring_free == DRIVER_RECEIVE_BUFFERS) {
+ return -1;
+ }
+
+ receive_ring[receive_ring_index] = desc;
+
+ receive_ring_index = (receive_ring_index + 1) % DRIVER_RECEIVE_BUFFERS;
+
+ dqval = e1000_dqval_val_insert(dqval, receive_ring_index);
+ e1000_rdt_wr(&e1000, 0, dqval);
+ receive_ring_free++;
+
+ return 0;
+ }
/*****************************************************************
- * MAC address
+ * get_mac_address_fn for net_queue_manager
+ *
+ * NOTE: This function gets called in ethersrv.c.
****************************************************************/
- /* NOTE: This function will get called from ethersrv.c */
static void get_mac_address_fn(uint8_t *mac)
{
- memcpy(mac, macaddr, sizeof(macaddr));
+ memcpy(mac, mac_address, sizeof(mac_address));
}
- static bool parse_mac(uint8_t *mac, const char *str)
+ /*****************************************************************
+ * find_tx_free_slot for net_queue_manager
+ *
+ *****************************************************************/
+ static uint64_t find_tx_free_slot_count_fn(void)
{
- for (int i = 0; i < 6; i++) {
- char *next = NULL;
- unsigned long val = strtoul(str, &next, 16);
- if (val > UINT8_MAX || next == NULL
- || (i == 5 && *next != '\0')
- || (i < 5 && (*next != ':' && *next != '-'))) {
- return false; // parse error
- }
- mac[i] = val;
- str = next + 1;
+ uint64_t free_slots;
+
+ if (ether_transmit_index >= ether_transmit_bufptr_index) {
+ free_slots = DRIVER_TRANSMIT_BUFFERS
+ - ((ether_transmit_index - ether_transmit_bufptr_index)
+ % DRIVER_TRANSMIT_BUFFERS);
+ } else {
+ free_slots = (ether_transmit_bufptr_index - ether_transmit_index)
+ % DRIVER_TRANSMIT_BUFFERS;
}
- return true;
+ return free_slots;
}
/*****************************************************************
* Transmit logic
- ****************************************************************/
- /* check if there are enough free buffers with driver,
+ *
+ * Check if there are enough free buffers with driver,
* so that packet can be sent
- * */
- static bool can_transmit(int numbufs)
+ ****************************************************************/
+ static bool can_transmit(uint64_t numbufs)
{
- uint64_t nr_free;
- assert(numbufs < DRIVER_TRANSMIT_BUFFER);
- if (ether_transmit_index >= ether_transmit_bufptr) {
- nr_free = DRIVER_TRANSMIT_BUFFER -
- ((ether_transmit_index - ether_transmit_bufptr) %
- DRIVER_TRANSMIT_BUFFER);
- } else {
- nr_free = (ether_transmit_bufptr - ether_transmit_index) %
- DRIVER_TRANSMIT_BUFFER;
+ uint64_t free_slots;
+
+ assert(numbufs < DRIVER_TRANSMIT_BUFFERS);
+
+ free_slots = find_tx_free_slot_count_fn();
+
+ return (free_slots > numbufs);
+ }
+
+ /*****************************************************************
+ * handle_free_TX_slot_fn for net_queue_manager
+ *
+ *****************************************************************/
+ static bool handle_free_TX_slot_fn(void)
+ {
+ uint64_t ts = rdtsc();
+ bool sent = false;
+ volatile struct tx_desc *txd;
+
+ if (ether_transmit_bufptr_index == ether_transmit_index) {
+ return false;
+ }
+
+ txd = &transmit_ring[ether_transmit_bufptr_index];
+ if (txd->ctrl.legacy.stat_rsv.d.dd != 1) {
+ return false;
++
}
- return (nr_free > numbufs);
+
+ #if TRACE_ONLY_SUB_NNET
+ trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_TXDRVSEE, 0);
+ #endif
+
- sent = handle_tx_done(pbuf_list_tx[ether_transmit_bufptr_index].sr,
- pbuf_list_tx[ether_transmit_bufptr_index].spp_index);
++ sent = handle_tx_done(pbuf_list_tx[ether_transmit_bufptr_index].s.opaque);
+
+ ether_transmit_bufptr_index = (ether_transmit_bufptr_index + 1)
+ % DRIVER_TRANSMIT_BUFFERS;
+ netbench_record_event_simple(bm, RE_TX_DONE, ts);
+
+ return true;
}
- static uint64_t transmit_pbuf(uint64_t buffer_address,
+ /*****************************************************************
+ * Setup transmit descriptor for packet transmission.
+ *
+ *****************************************************************/
-static uint64_t transmit_pbuf(lpaddr_t buffer_address, size_t packet_len,
- uint64_t offset, bool last, uint64_t client_data, uint64_t spp_index,
- struct net_queue_manager_binding *sr)
++ static uint64_t transmit_pbuf(uint64_t buffer_address,
+ size_t packet_len, bool last, void *opaque)
{
-
+ e1000_dqval_t dqval = 0;
struct tx_desc tdesc;
- tdesc.buffer_address = (uint64_t) buffer_address + offset;
+ tdesc.buffer_address = buffer_address;
tdesc.ctrl.raw = 0;
tdesc.ctrl.legacy.data_len = packet_len;
tdesc.ctrl.legacy.cmd.d.rs = 1;
tdesc.ctrl.legacy.cmd.d.ifcs = 1;
tdesc.ctrl.legacy.cmd.d.eop = (last ? 1 : 0);
+ /* FIXME: the packet should be copied into separate location, so that
+ * application can't temper with it. */
transmit_ring[ether_transmit_index] = tdesc;
- pbuf_list_tx[ether_transmit_index].sr = sr;
- pbuf_list_tx[ether_transmit_index].spp_index = spp_index;
+ pbuf_list_tx[ether_transmit_index].opaque = opaque;
- ether_transmit_index = (ether_transmit_index + 1) % DRIVER_TRANSMIT_BUFFER;
- e1000_tdt_wr(&(d), 0, (e1000_dqval_t){ .val = ether_transmit_index });
+ ether_transmit_index = (ether_transmit_index + 1) % DRIVER_TRANSMIT_BUFFERS;
+ dqval = e1000_dqval_val_insert(dqval, ether_transmit_index);
+ e1000_tdt_wr(&(e1000), 0, dqval);
+
+ E1000_DEBUG("ether_transmit_index %"PRIu32"\n", ether_transmit_index);
- E1000N_DEBUG("ether_transmit_index %"PRIu32"\n", ether_transmit_index);
/* Actual place where packet is sent. Adding trace_event here */
#if TRACE_ETHERSRV_MODE
trace_event(TRACE_SUBSYS_NET, TRACE_EVENT_NET_NO_S,
return 0;
}
-
- /* Send the buffer to device driver TX ring.
- * NOTE: This function will get called from ethersrv.c */
+ /*****************************************************************
+ * transmit_pbuf_list_fn for net_queue_manager
+ *
+ * Send the buffer to device driver TX ring.
+ *
+ * NOTE: This function get called from ethersrv.c
+ *****************************************************************/
-static errval_t transmit_pbuf_list_fn(struct client_closure *cl)
-{
- struct shared_pool_private *spp = cl->spp_ptr;
- struct slot_data *sld = &spp->sp->slot_list[cl->tx_index].d;
- uint64_t rtpbuf = sld->no_pbufs;
- struct buffer_descriptor *cached_buffer;
+static errval_t transmit_pbuf_list_fn(struct driver_buffer *buffers,
+ size_t count,
+ void *opaque)
+
- if (!can_transmit(rtpbuf)) {
- while (handle_free_TX_slot_fn())
- ;
+{
- errval_t r;
+ E1000N_DEBUG("transmit_pbuf_list_fn(count=%"PRIu64")\n", count);
+ if (!can_transmit(count)){
+ while(handle_free_TX_slot_fn());
+ if (!can_transmit(count)){
+
return ETHERSRV_ERR_CANT_TRANSMIT;
}
}
-
- cached_buffer = find_buffer(sld->buffer_id);
-
- if (cached_buffer == NULL) {
+ USER_PANIC("find_buffer failed.\n");
- abort();
- }
-
- // FIXME: code should work with following assert enable.
- // Current problem is that, ARP request packets are reused to send the
- // response, and hence having different buffer_id than of tx buffer
- // assert(buffer == cl->buffer_ptr);
-
- for (int i = 0; i < rtpbuf; i++) {
- struct buffer_descriptor *buffer;
- uint64_t slot_index;
- errval_t err;
+
- slot_index = (cl->tx_index + i) % cl->spp_ptr->c_size;
- sld = &spp->sp->slot_list[slot_index].d;
- assert(sld != NULL);
- if (sld->buffer_id == 0) {
- E1000_PRINT_ERROR("TX malformed packet at slot index %"PRIu64".\n",
- slot_index);
- return -1;
- }
-
- if (cached_buffer->buffer_id == sld->buffer_id) {
- buffer = cached_buffer;
- } else {
- buffer = find_buffer(sld->buffer_id);
+ if (count > 1) {
+ printf("Sending %zx chunks\n", count);
+ }
-
+ for (int i = 0; i < count; i++) {
+ r = transmit_pbuf(buffers[i].pa, buffers[i].len,
+ i == (count - 1), //last?
+ opaque);
+ if(err_is_fail(r)) {
+ //E1000N_DEBUG("ERROR:transmit_pbuf failed\n");
+ printf("ERROR:transmit_pbuf failed\n");
+ return r;
}
+ E1000N_DEBUG("transmit_pbuf done for pbuf 0x%p, index %i\n",
+ opaque, i);
+ } // end for: for each pbuf
+#if TRACE_ONLY_SUB_NNET
+ trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_TXDRVADD,
+ (uint32_t)0);
+#endif // TRACE_ONLY_SUB_NNET
- assert(buffer->buffer_id == sld->buffer_id);
+ return SYS_ERR_OK;
+} // end function: transmit_pbuf_list_fn
- err = transmit_pbuf(buffer->pa, sld->len, sld->offset,
- i == (rtpbuf - 1), /* last? */
- sld->client_data, slot_index, cl->app_connection);
- static uint64_t find_tx_free_slot_count_fn(void)
- {
- uint64_t nr_free;
- if (ether_transmit_index >= ether_transmit_bufptr) {
- nr_free = DRIVER_TRANSMIT_BUFFER -
- ((ether_transmit_index - ether_transmit_bufptr) %
- DRIVER_TRANSMIT_BUFFER);
- } else {
- nr_free = (ether_transmit_bufptr - ether_transmit_index) %
- DRIVER_TRANSMIT_BUFFER;
- }
- return nr_free;
- } // end function: find_tx_queue_len
-
- static bool handle_free_TX_slot_fn(void)
- {
- uint64_t ts = rdtsc();
- bool sent = false;
- volatile struct tx_desc *txd;
- if (ether_transmit_bufptr == ether_transmit_index) {
- return false;
- }
-
- txd = &transmit_ring[ether_transmit_bufptr];
- if (txd->ctrl.legacy.sta_rsv.d.dd != 1) {
- return false;
- }
-
- #if TRACE_ONLY_SUB_NNET
- trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_TXDRVSEE,
- 0);
- #endif // TRACE_ONLY_SUB_NNET
-
- if (err_is_fail(err)) {
- E1000_PRINT_ERROR("transmit_pbuf failed.\n");
- return err;
- }
- sent = handle_tx_done(pbuf_list_tx[ether_transmit_bufptr].opaque);
- E1000_DEBUG("transmit_pbuf done for pbuf %"PRIx64", index %"PRIu64"\n", sld->client_data, slot_index);
- }
- ether_transmit_bufptr = (ether_transmit_bufptr + 1)%DRIVER_TRANSMIT_BUFFER;
- netbench_record_event_simple(bm, RE_TX_DONE, ts);
- return true;
- }
-#if TRACE_ONLY_SUB_NNET
- trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_TXDRVADD, (uint32_t)0);
-#endif
- return SYS_ERR_OK;
-}
/*****************************************************************
- * Initialize internal memory for the device
- ****************************************************************/
-
-
+ *
+ *
+ *
+ *****************************************************************/
+static int add_desc(uint64_t paddr, void *opaque)
+{
+ union rx_desc r;
+ r.raw[0] = r.raw[1] = 0;
+ r.rx_read_format.buffer_address = paddr;
+
+ if(receive_free == DRIVER_RECEIVE_BUFFERS) {
+ // This is serious error condition.
+ // Printing debug information to help user!
+ //E1000N_DEBUG("no space to add a new receive pbuf\n");
+ printf("no space to add a new receive pbuf [%"PRIu32"], [%"PRIu32"]\n",
+ receive_free, receive_index);
+ printf("%p\n%p\n%p\n", __builtin_return_address(0),
+ __builtin_return_address(1), __builtin_return_address(2));
+ abort();
+ /* FIXME: how can you return -1 as error here
+ * when return type is unsigned?? */
+ return -1;
+ }
+
+ receive_ring[receive_index] = r;
+ receive_opaque[receive_index] = opaque;
+
+ receive_index = (receive_index + 1) % DRIVER_RECEIVE_BUFFERS;
+ e1000_rdt_wr(&d, 0, (e1000_dqval_t){ .val=receive_index } );
+ receive_free++;
+ return 0;
+}
+
- static void setup_internal_memory(void)
- {
- receive_opaque = calloc(sizeof(void *), DRIVER_RECEIVE_BUFFERS);
- }
+
+static errval_t rx_register_buffer_fn(uint64_t paddr, void *vaddr, void *opaque)
+{
+ return add_desc(paddr, opaque);
+}
-
+static uint64_t rx_find_free_slot_count_fn(void)
+{
+ return DRIVER_RECEIVE_BUFFERS - receive_free;
+}
+
+static void print_rx_bm_stats(bool stop_trace)
+{
+ if (g_cl == NULL) {
+ return;
+ }
+
+ if (g_cl->debug_state != 4) {
+ return;
+ }
+
+ uint64_t cts = rdtsc();
+
+ if (stop_trace) {
+
+#if TRACE_N_BM
+ // stopping the tracing
+ trace_event(TRACE_SUBSYS_BNET, TRACE_EVENT_BNET_STOP, 0);
+
+ /*
+ char *buf = malloc(4096*4096);
+ trace_dump(buf, 4096*4096);
+ printf("%s\n", buf);
+ */
+#endif // TRACE_N_BM
+
+ } // end if: stop_trace
+
+ uint64_t running_time = cts - g_cl->start_ts;
+ printf("D:I:%u: RX speed = [%"PRIu64"] packets "
+ "data(%"PRIu64") / time(%"PU") = [%f] MB/s ([%f]Mbps) = "
+ " [%f]mpps, INT [%"PRIu64"]\n",
+ disp_get_core_id(),
+ total_rx_p_count, total_rx_datasize, in_seconds(running_time),
+ ((total_rx_datasize/in_seconds(running_time))/(1024 * 1024)),
+ (((total_rx_datasize * 8)/in_seconds(running_time))/(1024 * 1024)),
+ ((total_rx_p_count/in_seconds(running_time))/(double)(1000000)),
+ interrupt_counter
+ );
+
+ netbench_print_event_stat(bm, RE_COPY, "D: RX CP T", 1);
+ netbench_print_event_stat(bm, RE_PROCESSING_ALL, "D: RX processing T", 1);
+} // end function: print_rx_bm_stats
+
+static char tmp_buf[2000];
static bool handle_next_received_packet(void)
{
volatile union rx_desc *rxd;
+ size_t len = 0;
bool new_packet = false;
- tmp_buf[0] = 0; // FIXME: to avoid the warning of not using this variable
+ errval_t err;
- if (receive_bufptr == receive_index) { //no packets received
+ if (receive_bufptr_index == receive_ring_index) {
return false;
}
- // E1000N_DEBUG("Inside handle next packet 2\n");
- rxd = &receive_ring[receive_bufptr];
+ rxd = &receive_ring[receive_bufptr_index];
- if ((rxd->rx_read_format.info.status.dd) &&
- (rxd->rx_read_format.info.status.eop)
- // && (!local_pbuf[receive_bufptr].event_sent)
- ) {
- // valid packet received
+ if ((rxd->rx_read_format.info.status.dd)
+ && (rxd->rx_read_format.info.status.eop)) {
+ struct buffer_descriptor *buffer = NULL;
+ void *buffer_address = NULL;
+ void *data = NULL;
+ size_t len = 0;
- E1000N_DPRINT("Potential packet receive [%"PRIu32"]!\n",
- receive_bufptr);
+ /* A valid packet received */
-
+ E1000_DEBUG("Potential packet receive [%"PRIu32"]!\n", receive_bufptr_index);
-
new_packet = true;
+
+ /* Ensures that netd is up and running */
+ if (waiting_for_netd()) {
+ E1000_DEBUG("still waiting for netd to register buffers.\n");
+ buffer = NULL;
+ goto end;
+ }
+
len = rxd->rx_read_format.info.length;
+
+ if (len > RX_PACKET_MAX_LEN) {
+ E1000_DEBUG("Dropping packet with invalid length %zu.\n", len);
+ goto end;
+ }
total_rx_datasize += len;
#if TRACE_ONLY_SUB_NNET
trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_RXDRVSEE,
(uint32_t) len);
- #endif // TRACE_ONLY_SUB_NNET
+ #endif
+
+ buffer_address = (void *) rxd->rx_read_format.buffer_address;
+ data = (buffer_address - receive_ring_phys_addr)
+ + receive_ring_virt_addr;
-
+ if (data == NULL || len == 0) {
+ E1000_DEBUG("Dropping incorrect packet.\n");
+ // FIXME: What should I do when such errors occur.
+ buffer = NULL;
+ goto end;
+ }
- process_received_packet(receive_opaque[receive_bufptr], len, true);
+ #if !defined(__scc__) && !defined(__i386__)
+ cache_flush_range(data, len);
+ #endif
- #if 0
- // This code is useful for RX micro-benchmark
- // only to measures performance of accepting incoming packets
+ #ifdef CONFIG_MICROBENCHMARKS
+ /* This code is useful for RX micro-benchmark
+ * only to measure performance of accepting incoming packets */
if (g_cl != NULL) {
if (g_cl->debug_state == 4) {
-
uint64_t ts = rdtsc();
- // memcpy_fast(tmp_buf, data, len);
process_received_packet(data, len);
total_processing_time = total_processing_time +
- (rdtsc() - ts);
-
+ (rdtsc() - ts);
} else {
process_received_packet(data, len);
}
++poll_count;
ts = rdtsc();
- do_pending_work_for_all();
+// do_pending_work_for_all();
netbench_record_event_simple(bm, RE_PENDING_WORK, ts);
- err = event_dispatch_non_block(ws);
+// err = event_dispatch(ws); // blocking // doesn't work correctly
- err = event_dispatch_non_block(ws); // nonblocking
- if (err != LIB_ERR_NO_EVENT) {
- if (err_is_fail(err)) {
- DEBUG_ERR(err, "in event_dispatch_non_block");
- break;
- } else {
- // Handled some event dispatch
- no_work = false;
- }
+ if (err != LIB_ERR_NO_EVENT && err_is_fail(err)) {
+ E1000_DEBUG("Error in event_dispatch_non_block, returned %d\n",
+ (unsigned int)err);
+ break;
+ } else {
+ no_work = false;
}
#if TRACE_N_BM
int main(int argc, char **argv)
{
char *service_name = 0;
- errval_t r;
+ errval_t err;
+ /** Parse command line arguments. */
+ for (int i = 1; i < argc; i++) {
+ E1000N_DEBUG("e1000 standalone driver started.\n");
+
+ E1000N_DEBUG("argc = %d\n", argc);
+ for (int i = 0; i < argc; i++) {
+ E1000N_DEBUG("arg %d = %s\n", i, argv[i]);
- if(strncmp(argv[i],"servicename=",strlen("servicename=")-1)==0) {
+ if (strncmp(argv[i], "affinitymin=", strlen("affinitymin=")) == 0) {
+ minbase = atol(argv[i] + strlen("affinitymin="));
+ E1000_DEBUG("minbase = %lu\n", minbase);
+ }
+
+ else if (strncmp(argv[i], "affinitymax=", strlen("affinitymax="))
+ == 0) {
+ maxbase = atol(argv[i] + strlen("affinitymax="));
+ E1000_DEBUG("maxbase = %lu\n", maxbase);
+ }
+
+ else if (strncmp(argv[i], "servicename=", strlen("servicename="))
+ == 0) {
service_name = argv[i] + strlen("servicename=");
- E1000N_DEBUG("service name = %s\n", service_name);
+ E1000_DEBUG("service name = %s\n", service_name);
- }
+ } else if(strncmp(argv[i],"bus=",strlen("bus=")-1)==0) {
+
+ else if (strncmp(argv[i], "bus=", strlen("bus=")) == 0) {
bus = atol(argv[i] + strlen("bus="));
- E1000N_DEBUG("bus = %lu\n", bus);
- } else if(strncmp(argv[i],"device=",strlen("device=")-1)==0) {
+ E1000_DEBUG("bus = %ul\n", bus);
+ use_force = true;
+ }
+
+ else if (strncmp(argv[i], "device=", strlen("device=")) == 0) {
device = atol(argv[i] + strlen("device="));
- E1000N_DEBUG("device = %lu\n", device);
- } else if(strncmp(argv[i],"function=",strlen("function=")-1)==0) {
+ E1000_DEBUG("device = %ul\n", device);
+ use_force = true;
+ }
+
+ else if (strncmp(argv[i], "function=", strlen("function=")) == 0) {
function = atol(argv[i] + strlen("function="));
- E1000N_DEBUG("function = %u\n", function);
- } else if(strncmp(argv[i],"deviceid=",strlen("deviceid=")-1)==0) {
+ E1000_DEBUG("function = %u\n", function);
+ use_force = true;
+ }
+
+ else if (strncmp(argv[i], "deviceid=", strlen("deviceid=")) == 0) {
deviceid = strtoul(argv[i] + strlen("deviceid="), NULL, 0);
- E1000N_DEBUG("deviceid = %u\n", deviceid);
- printf("### deviceid = %u\n", deviceid);
- } else if(strncmp(argv[i],"mac=",strlen("mac=")-1)==0) {
- if (parse_mac(macaddr, argv[i] + strlen("mac="))) {
- user_macaddr = true;
- E1000N_DEBUG("MAC= %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
- macaddr[0], macaddr[1], macaddr[2],
- macaddr[3], macaddr[4], macaddr[5]);
+ E1000_DEBUG("deviceid = %u\n", deviceid);
+ use_force = true;
- }
+
+ else if (strncmp(argv[i], "mac=", strlen("mac=")) == 0) {
+ if (parse_mac(mac_address, argv[i] + strlen("mac="))) {
+ user_mac_address = true;
+ E1000_DEBUG("MAC= %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
+ mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]);
} else {
- fprintf(stderr, "%s: Error parsing MAC address '%s'\n",
- argv[0], argv[i]);
- return 1;
+ E1000_PRINT_ERROR("Error: Failed parsing MAC address '%s'.\n", argv[i]);
+ exit(1);
}
- }
+ } else if(strcmp(argv[i],"noirq")==0) {
+
+ else if (strcmp(argv[i], "noirq") == 0) {
+ E1000_DEBUG("Driver working in polling mode.\n");
use_interrupt = false;
- printf("Driver working in polling mode\n");
- } else {
- // Pass argument to library
- ethersrv_argument(argv[i]);
}
+
+ else if (strcmp(argv[i], "-h") == 0 ||
+ strcmp(argv[i], "--help") == 0) {
+ exit_help(argv[0]);
+ }
+
+ else {
+ E1000_PRINT_ERROR("Error: unknown argument: %s.\n", argv[i]);
+ exit_help(argv[0]);
+ }
+ }
+
+ if ((minbase != -1) && (maxbase != -1)) {
+ E1000_DEBUG("set memory affinity [%lx, %lx]\n", minbase, maxbase);
+ ram_set_affinity(minbase, maxbase);
}
if (service_name == 0) {