stable, merging to master branch
This commit is contained in:
parent
cadd5a21a4
commit
c34be253f7
@ -1,5 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
find_program(CC_GCC gcc)
|
||||
find_program(CXX_GCC g++)
|
||||
|
||||
set(CMAKE_C_COMPILER ${CC_GCC})
|
||||
set(CMAKE_CXX_COMPILER ${CXX_GCC})
|
||||
|
||||
project(khat)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
|
||||
@ -13,7 +19,7 @@ include_directories(${dpdk_INCLUDE_DIRS})
|
||||
add_executable(khat khat/khat.cc)
|
||||
add_executable(cat cat/cat.cc)
|
||||
|
||||
set(LINK_LIBS ${dpdk_LIBRARIES} pthread numa)
|
||||
set(LINK_LIBS ${dpdk_LIBRARIES} pthread)
|
||||
|
||||
target_link_libraries(khat ${LINK_LIBS})
|
||||
target_compile_options(khat PRIVATE ${CC_FLAGS})
|
||||
|
138
cat/cat.cc
138
cat/cat.cc
@ -1,3 +1,4 @@
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <netinet/in.h>
|
||||
#include <rte_config.h>
|
||||
@ -15,15 +16,23 @@
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ntrlog.h"
|
||||
#include "pkt.h"
|
||||
#include "rte_byteorder.h"
|
||||
|
||||
constexpr unsigned int MBUF_MAX_COUNT = 1024;
|
||||
constexpr unsigned int MBUF_CACHE_SIZE = 256;
|
||||
// init NTRLOG
|
||||
NTR_DECL_IMPL;
|
||||
|
||||
constexpr unsigned int MBUF_MAX_COUNT = 8191;
|
||||
constexpr unsigned int MBUF_CACHE_SIZE = 250;
|
||||
constexpr unsigned int RX_RING_SIZE = 1024;
|
||||
constexpr unsigned int TX_RING_SIZE = 1024;
|
||||
constexpr unsigned int RX_RING_NUM = 1;
|
||||
constexpr unsigned int TX_RING_NUM = 1;
|
||||
constexpr unsigned int BURST_SIZE = 4;
|
||||
constexpr unsigned int BURST_SIZE = 32;
|
||||
|
||||
|
||||
static const struct rte_eth_conf port_conf_default{};
|
||||
|
||||
struct datapt{
|
||||
uint64_t server_proc = 0;
|
||||
@ -58,11 +67,12 @@ rx_calc_latency(uint16_t port __rte_unused, uint16_t qidx __rte_unused,
|
||||
pkt_data = check_valid_packet(pkts[i]);
|
||||
|
||||
if (pkt_data == NULL) {
|
||||
rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1, "rx_calc_latency: ignoring invalid packet 0x%p.", (void*)pkts[i]);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_DEBUG, "rx_calc_latency: ignoring invalid packet 0x%p.\n", (void*)pkts[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
pkt_data->clt_ts_rx = htonll(now);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "rx_calc_latency: tagged packet %p with %llu.\n", (void*)pkts[i], now);
|
||||
pkt_data->clt_ts_rx = rte_cpu_to_be_64(now);
|
||||
}
|
||||
|
||||
return nb_pkts;
|
||||
@ -80,11 +90,12 @@ tx_add_timestamp(uint16_t port __rte_unused, uint16_t qidx __rte_unused,
|
||||
pkt_data = check_valid_packet(pkts[i]);
|
||||
|
||||
if (pkt_data == NULL) {
|
||||
rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1, "tx_add_timestamp: ignoring invalid packet 0x%p.", (void*)pkts[i]);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_DEBUG, "tx_add_timestamp: ignoring invalid packet 0x%p.\n", (void*)pkts[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
pkt_data->clt_ts_tx = htonll(now);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "tx_add_timestamp: tagged packet %p with %llu.\n", (void*)pkts[i], now);
|
||||
pkt_data->clt_ts_tx = rte_cpu_to_be_64(now);
|
||||
}
|
||||
|
||||
return nb_pkts;
|
||||
@ -104,25 +115,29 @@ locore_main(void * _unused __rte_unused)
|
||||
int state = STATE_SEND;
|
||||
|
||||
if (rte_eth_dev_socket_id(options.s_portid) > 0 && rte_eth_dev_socket_id(options.s_portid) != (int)rte_socket_id()) {
|
||||
rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1, "locore_main: WARNING, port %d is on remote NUMA node to "
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_WARNING, "locore_main: WARNING, port %d is on remote NUMA node to "
|
||||
"polling thread.\n\tPerformance will "
|
||||
"not be optimal.\n", options.s_portid);
|
||||
}
|
||||
|
||||
rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "locore_main: core %d sending packets... [Ctrl+C to quit]\n", core_id);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "locore_main: core %d running...\n", core_id);
|
||||
|
||||
tx_buf = rte_pktmbuf_alloc(options.s_mbuf_pool);
|
||||
|
||||
if (tx_buf == NULL) {
|
||||
rte_exit(EXIT_FAILURE, "cannot allocate tx_buf");
|
||||
rte_exit(EXIT_FAILURE, "cannot allocate tx_buf\n");
|
||||
}
|
||||
|
||||
tx_buf->l2_len = sizeof(struct rte_ether_hdr);
|
||||
tx_buf->nb_segs = 1;
|
||||
|
||||
pkt_data = (struct packet_data *)rte_pktmbuf_append(tx_buf, sizeof(struct packet_data));
|
||||
if (pkt_data == NULL) {
|
||||
rte_exit(EXIT_FAILURE, "cannot allocate space for packet_data in mbuf");
|
||||
rte_exit(EXIT_FAILURE, "cannot allocate space for packet_data in mbuf\n");
|
||||
}
|
||||
|
||||
// construct the packet ether type
|
||||
pkt_data->eth_hdr.ether_type = 0x1234;
|
||||
pkt_data->magic = rte_cpu_to_be_32(ETHER_FRAME_MAGIC);
|
||||
pkt_data->eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
|
||||
rte_ether_addr_copy(&options.server_mac, &pkt_data->eth_hdr.d_addr);
|
||||
rte_ether_addr_copy(&options.s_host_mac, &pkt_data->eth_hdr.s_addr);
|
||||
|
||||
@ -136,18 +151,18 @@ locore_main(void * _unused __rte_unused)
|
||||
struct packet_data * each = check_valid_packet(rx_bufs[i]);
|
||||
|
||||
if (each == NULL) {
|
||||
rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1, "locore_main: ignoring invalid packet 0x%p.", (void*)rx_bufs[i]);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_DEBUG, "locore_main: ignoring invalid packet %p.\n", (void*)rx_bufs[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (each->epoch == epoch) {
|
||||
rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "locore_main: received packet 0x%p for epoch %d", (void*)rx_bufs[i], epoch);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "locore_main: received packet %p for epoch %d\n", (void*)rx_bufs[i], epoch);
|
||||
|
||||
if (options.s_record.load()) {
|
||||
// keep statistics
|
||||
struct datapt * dpt = new datapt;
|
||||
dpt->rtt = ntohll(pkt_data->clt_ts_rx) - ntohll(pkt_data->clt_ts_tx);
|
||||
dpt->server_proc = ntohll(pkt_data->srv_ts_tx) - ntohll(pkt_data->srv_ts_rx);
|
||||
dpt->rtt = rte_be_to_cpu_64(each->clt_ts_rx) - rte_be_to_cpu_64(each->clt_ts_tx);
|
||||
dpt->server_proc = rte_be_to_cpu_64(each->srv_ts_tx) - rte_be_to_cpu_64(each->srv_ts_rx);
|
||||
options.s_stats.push_back(dpt);
|
||||
}
|
||||
|
||||
@ -156,7 +171,7 @@ locore_main(void * _unused __rte_unused)
|
||||
epoch++;
|
||||
break;
|
||||
} else {
|
||||
rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1, "locore_main: ignoring packet 0x%p with invalid epoch %d.", (void*)rx_bufs[i], epoch);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "locore_main: ignoring packet 0x%p with invalid epoch %d.\n", (void*)rx_bufs[i], epoch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,19 +179,20 @@ locore_main(void * _unused __rte_unused)
|
||||
if (state == STATE_SEND) {
|
||||
// set new epoch
|
||||
pkt_data->epoch = epoch;
|
||||
rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "locore_main: sending packet 0x%p with epoch %d", (void*)tx_buf, epoch);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "locore_main: sending packet %p with epoch %d\n", (void*)tx_buf, epoch);
|
||||
|
||||
const uint16_t nb_tx = rte_eth_tx_burst(options.s_portid, 0, &tx_buf, 1);
|
||||
|
||||
if (nb_tx < 1) {
|
||||
rte_exit(EXIT_FAILURE, "failed to send packet 0x%p, epoch %d", (void*)tx_buf, epoch);
|
||||
rte_exit(EXIT_FAILURE, "failed to send packet 0x%p, epoch %d\n", (void*)tx_buf, epoch);
|
||||
}
|
||||
state = STATE_RECV;
|
||||
}
|
||||
}
|
||||
|
||||
rte_pktmbuf_free(tx_buf);
|
||||
|
||||
rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "locore_main: core %d successfully stopped.", core_id);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "locore_main: core %d successfully stopped.\n", core_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -185,8 +201,9 @@ static int
|
||||
port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
|
||||
{
|
||||
struct rte_eth_dev_info dev_info;
|
||||
struct rte_eth_conf port_conf;
|
||||
struct rte_eth_conf port_conf = port_conf_default;
|
||||
struct rte_eth_txconf txconf;
|
||||
struct rte_eth_rxconf rxconf;
|
||||
|
||||
uint16_t nb_rxd = RX_RING_SIZE;
|
||||
uint16_t nb_txd = TX_RING_SIZE;
|
||||
@ -203,10 +220,7 @@ port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
|
||||
|
||||
if(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
|
||||
port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE;
|
||||
if(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)
|
||||
port_conf.txmode.offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM;
|
||||
if(dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM)
|
||||
port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_IPV4_CKSUM;
|
||||
port_conf.rxmode.max_rx_pkt_len = RTE_ETHER_MAX_LEN;
|
||||
|
||||
/* Configure the Ethernet device. */
|
||||
ret = rte_eth_dev_configure(portid, RX_RING_NUM, TX_RING_NUM, &port_conf);
|
||||
@ -218,6 +232,8 @@ port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
|
||||
return ret;
|
||||
|
||||
/* Allocate and set up 1 RX queue per Ethernet port. */
|
||||
rxconf = dev_info.default_rxconf;
|
||||
rxconf.offloads = port_conf.rxmode.offloads;
|
||||
for (uint32_t i = 0; i < RX_RING_NUM; i++) {
|
||||
ret = rte_eth_rx_queue_setup(portid, i, nb_rxd, rte_eth_dev_socket_id(portid), NULL, mbuf_pool);
|
||||
if (ret < 0)
|
||||
@ -242,16 +258,9 @@ port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
|
||||
ret = rte_eth_macaddr_get(portid, &addr);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
|
||||
" %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
|
||||
portid,
|
||||
addr.addr_bytes[0], addr.addr_bytes[1],
|
||||
addr.addr_bytes[2], addr.addr_bytes[3],
|
||||
addr.addr_bytes[4], addr.addr_bytes[5]);
|
||||
|
||||
/* Enable RX in promiscuous mode for the Ethernet device. */
|
||||
ret = rte_eth_promiscuous_enable(portid);
|
||||
ret = rte_eth_promiscuous_enable(portid);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
@ -261,41 +270,59 @@ port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_options()
|
||||
{
|
||||
fprintf(stdout, "Configuration:\n" \
|
||||
" run time = %d\n" \
|
||||
" warmup time = %d\n" \
|
||||
" output file = %s\n" \
|
||||
" server MAC = %x:%x:%x:%x:%x:%x\n",
|
||||
options.run_time,
|
||||
options.warmup_time,
|
||||
options.output,
|
||||
options.server_mac.addr_bytes[0],
|
||||
options.server_mac.addr_bytes[1],
|
||||
options.server_mac.addr_bytes[2],
|
||||
options.server_mac.addr_bytes[3],
|
||||
options.server_mac.addr_bytes[4],
|
||||
options.server_mac.addr_bytes[5]);
|
||||
}
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stdout, "Usage:\n \
|
||||
-v: verbose mode\n \
|
||||
-h: display the information\n");
|
||||
-h: display the information\n\n");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
unsigned int nb_ports;
|
||||
struct rte_mempool *mbuf_pool;
|
||||
struct rte_mempool *mbuf_pool, *mbuf_pool_pkt;
|
||||
std::ofstream log_file;
|
||||
|
||||
// init dpdk
|
||||
int ret = rte_eal_init(argc, argv);
|
||||
if (ret < 0) {
|
||||
rte_exit(EXIT_FAILURE, "rte_eal_init failed!");
|
||||
rte_exit(EXIT_FAILURE, "rte_eal_init failed!\n");
|
||||
}
|
||||
|
||||
argc -= ret;
|
||||
argv += ret;
|
||||
|
||||
// set warning level
|
||||
rte_log_set_level(RTE_LOGTYPE_USER1, RTE_LOG_WARNING);
|
||||
ntr_set_level(NTR_DEP_USER1, NTR_LEVEL_WARNING);
|
||||
{
|
||||
int c;
|
||||
// parse arguments
|
||||
while((c = getopt(argc, argv, "hvo:t:T:s:")) != -1) {
|
||||
switch (c) {
|
||||
case 'v':
|
||||
rte_log_set_level(RTE_LOGTYPE_USER1, RTE_LOG_INFO);
|
||||
ntr_set_level(NTR_DEP_USER1, ntr_get_level(NTR_DEP_USER1) + 1);
|
||||
break;
|
||||
case 's':
|
||||
if (rte_ether_unformat_addr(optarg, &options.server_mac) == -1) {
|
||||
rte_exit(EXIT_FAILURE, "cannot parse %s as mac address.", optarg);
|
||||
rte_exit(EXIT_FAILURE, "cannot parse %s as mac address.\n", optarg);
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
@ -313,7 +340,7 @@ int main(int argc, char* argv[])
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
rte_exit(EXIT_FAILURE, "unknown argument: %c", c);
|
||||
rte_exit(EXIT_FAILURE, "unknown argument: %c\n", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -322,36 +349,41 @@ int main(int argc, char* argv[])
|
||||
// open log file for writing
|
||||
log_file.open(options.output, std::ofstream::out);
|
||||
if (!log_file) {
|
||||
rte_exit(EXIT_FAILURE, "failed to open log file");
|
||||
rte_exit(EXIT_FAILURE, "failed to open log file %s\n", options.output);
|
||||
}
|
||||
|
||||
nb_ports = rte_eth_dev_count_avail();
|
||||
if (nb_ports < 2 || (nb_ports & 1)) {
|
||||
rte_exit(EXIT_FAILURE, "number of ports must be even");
|
||||
if (nb_ports == 0) {
|
||||
rte_exit(EXIT_FAILURE, "number of ports must be > 0\n");
|
||||
}
|
||||
|
||||
// create a mbuf memory pool on the socket
|
||||
mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", MBUF_MAX_COUNT * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
|
||||
if (mbuf_pool == nullptr) {
|
||||
rte_exit(EXIT_FAILURE, "cannot create mbuf pool");
|
||||
rte_exit(EXIT_FAILURE, "cannot create mbuf pool\n");
|
||||
}
|
||||
options.s_mbuf_pool = mbuf_pool;
|
||||
|
||||
mbuf_pool_pkt = rte_pktmbuf_pool_create("MBUF_POOL_PKT", MBUF_MAX_COUNT * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
|
||||
if (mbuf_pool_pkt == nullptr) {
|
||||
rte_exit(EXIT_FAILURE, "cannot create mbuf pool\n");
|
||||
}
|
||||
options.s_mbuf_pool = mbuf_pool_pkt;
|
||||
|
||||
uint16_t portid = rte_eth_find_next(0);
|
||||
if (portid == RTE_MAX_ETHPORTS) {
|
||||
rte_exit(EXIT_FAILURE, "cannot find an available port");
|
||||
rte_exit(EXIT_FAILURE, "cannot find an available port\n");
|
||||
}
|
||||
options.s_portid = portid;
|
||||
|
||||
if (port_init(portid, mbuf_pool) != 0) {
|
||||
rte_exit(EXIT_FAILURE, "cannot init port %d", portid);
|
||||
rte_exit(EXIT_FAILURE, "cannot init port %d\n", portid);
|
||||
}
|
||||
|
||||
if (rte_eth_macaddr_get(portid, &options.s_host_mac) != 0) {
|
||||
rte_exit(EXIT_FAILURE, "cannot get mac address of port %d", portid);
|
||||
rte_exit(EXIT_FAILURE, "cannot get mac address of port %d\n", portid);
|
||||
}
|
||||
|
||||
rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "Configured port %d with mac addr %x-%x-%x-%x-%x-%x", portid,
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "Configured port %d with mac addr %x:%x:%x:%x:%x:%x\n", portid,
|
||||
options.s_host_mac.addr_bytes[0],
|
||||
options.s_host_mac.addr_bytes[1],
|
||||
options.s_host_mac.addr_bytes[2],
|
||||
@ -359,9 +391,11 @@ int main(int argc, char* argv[])
|
||||
options.s_host_mac.addr_bytes[4],
|
||||
options.s_host_mac.addr_bytes[5]);
|
||||
|
||||
dump_options();
|
||||
|
||||
uint16_t core_id = rte_get_next_lcore(0, true, false);
|
||||
if (rte_eal_remote_launch(locore_main, NULL, core_id) != 0) {
|
||||
rte_exit(EXIT_FAILURE, "failed to launch function on locore");
|
||||
rte_exit(EXIT_FAILURE, "failed to launch function on locore\n");
|
||||
}
|
||||
|
||||
// poor man's timer
|
||||
@ -383,7 +417,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
if (rte_eal_wait_lcore(core_id) < 0)
|
||||
rte_exit(EXIT_FAILURE, "failed to wait for job completion");
|
||||
rte_exit(EXIT_FAILURE, "failed to wait for job completion\n");
|
||||
|
||||
// dump stats
|
||||
for (auto it = std::begin(options.s_stats); it != std::end(options.s_stats); ++it) {
|
||||
|
61
inc/ntrlog.h
Normal file
61
inc/ntrlog.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define NTR_LEVEL_NONE (0)
|
||||
#define NTR_LEVEL_ERROR (1)
|
||||
#define NTR_LEVEL_WARNING (2)
|
||||
#define NTR_LEVEL_INFO (3)
|
||||
#define NTR_LEVEL_DEBUG (4)
|
||||
#define NTR_LEVEL_DEFAULT (NTR_LEVEL_WARNING)
|
||||
|
||||
#define NTR_DEP_NTR (0)
|
||||
#define NTR_DEP_USER1 (1)
|
||||
#define NTR_DEP_USER2 (2)
|
||||
#define NTR_DEP_USER3 (3)
|
||||
#define NTR_DEP_USER4 (4)
|
||||
#define NTR_DEP_USER5 (5)
|
||||
#define NTR_DEP_MAX (NTR_DEP_USER5 + 1)
|
||||
|
||||
#define NTR_DECL_IMPL \
|
||||
int ntr_log_levels[NTR_DEP_MAX] = {NTR_LEVEL_DEFAULT}; \
|
||||
FILE * ntr_out = stdout
|
||||
|
||||
extern int ntr_log_levels[];
|
||||
extern FILE * ntr_out;
|
||||
|
||||
static inline
|
||||
void ntr(int dep, int level, const char * fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
if (dep < NTR_DEP_MAX && level <= ntr_log_levels[dep]) {
|
||||
vfprintf(ntr_out, fmt, vl);
|
||||
}
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
static inline
|
||||
void ntr_set_level(int dep, int level)
|
||||
{
|
||||
if (dep < NTR_DEP_MAX) {
|
||||
ntr_log_levels[dep] = level;
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
void ntr_set_output(FILE * f)
|
||||
{
|
||||
if (f != NULL) {
|
||||
ntr_out = f;
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
int ntr_get_level(int dep)
|
||||
{
|
||||
if (dep < NTR_DEP_MAX) {
|
||||
return ntr_log_levels[dep];
|
||||
}
|
||||
return 0;
|
||||
}
|
31
inc/pkt.h
31
inc/pkt.h
@ -1,15 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_ip.h>
|
||||
#include <stdint.h>
|
||||
#include <rte_ether.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
constexpr static uint16_t ETHER_FRAME_MAGIC = 0x1234;
|
||||
|
||||
constexpr static uint32_t ETHER_FRAME_MAGIC = 0xDCDCE5E5;
|
||||
struct packet_data
|
||||
{
|
||||
struct rte_ether_hdr eth_hdr;
|
||||
uint32_t magic;
|
||||
uint32_t epoch;
|
||||
uint64_t clt_ts_tx;
|
||||
uint64_t clt_ts_rx;
|
||||
@ -28,27 +29,9 @@ struct packet_data * check_valid_packet(struct rte_mbuf * pkt)
|
||||
|
||||
pkt_data = rte_pktmbuf_mtod(pkt, struct packet_data *);
|
||||
|
||||
if (ntohs(pkt_data->eth_hdr.ether_type) != ETHER_FRAME_MAGIC) {
|
||||
return NULL;
|
||||
if (rte_be_to_cpu_16(pkt_data->eth_hdr.ether_type) == RTE_ETHER_TYPE_IPV4 && rte_be_to_cpu_32(pkt_data->magic) == ETHER_FRAME_MAGIC) {
|
||||
return pkt_data;
|
||||
}
|
||||
|
||||
return pkt_data;
|
||||
}
|
||||
|
||||
static inline uint64_t htonll(uint64_t x)
|
||||
{
|
||||
#if __BIG_ENDIAN__
|
||||
return x;
|
||||
#else
|
||||
return ((uint64_t)htonl((x) & 0xFFFFFFFFLL) << 32) | htonl((x) >> 32);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint64_t ntohll(uint64_t x)
|
||||
{
|
||||
#if __BIG_ENDIAN__
|
||||
return x;
|
||||
#else
|
||||
return ((uint64_t)ntohl((x) & 0xFFFFFFFFLL) << 32) | ntohl((x) >> 32);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
116
khat/khat.cc
116
khat/khat.cc
@ -1,3 +1,4 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <rte_common.h>
|
||||
#include <rte_eal.h>
|
||||
@ -5,20 +6,27 @@
|
||||
#include <rte_cycles.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_config.h>
|
||||
#include <rte_ether.h>
|
||||
#include <rte_launch.h>
|
||||
#include <atomic>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pkt.h"
|
||||
#include "rte_launch.h"
|
||||
#include "rte_log.h"
|
||||
#include "ntrlog.h"
|
||||
|
||||
constexpr unsigned int MBUF_MAX_COUNT = 1024;
|
||||
constexpr unsigned int MBUF_CACHE_SIZE = 256;
|
||||
NTR_DECL_IMPL;
|
||||
|
||||
constexpr unsigned int MBUF_MAX_COUNT = 8191;
|
||||
constexpr unsigned int MBUF_CACHE_SIZE = 250;
|
||||
constexpr unsigned int RX_RING_SIZE = 1024;
|
||||
constexpr unsigned int TX_RING_SIZE = 1024;
|
||||
constexpr unsigned int RX_RING_NUM = 1;
|
||||
constexpr unsigned int TX_RING_NUM = 1;
|
||||
constexpr unsigned int BURST_SIZE = 4;
|
||||
constexpr unsigned int BURST_SIZE = 32;
|
||||
|
||||
static const struct rte_eth_conf port_conf_default{};
|
||||
|
||||
struct options_t {
|
||||
//states
|
||||
@ -34,16 +42,16 @@ rx_add_timestamp(uint16_t port __rte_unused, uint16_t qidx __rte_unused,
|
||||
{
|
||||
uint64_t now = rte_rdtsc();
|
||||
struct packet_data * pkt_data;
|
||||
|
||||
for (int i = 0; i < nb_pkts; i++) {
|
||||
pkt_data = check_valid_packet(pkts[i]);
|
||||
|
||||
if (pkt_data == NULL) {
|
||||
rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1, "rx_add_timestamp: ignoring invalid packet 0x%p.", (void*)pkts[i]);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_DEBUG, "rx_add_timestamp: ignoring invalid packet %p.\n", (void*)pkts[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
pkt_data->srv_ts_rx = htonll(now);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "rx_add_timestamp: tagged packet %p with %llu.\n", (void*)pkts[i], now);
|
||||
pkt_data->srv_ts_rx = rte_cpu_to_be_64(now);
|
||||
}
|
||||
|
||||
return nb_pkts;
|
||||
@ -61,11 +69,12 @@ tx_calc_latency(uint16_t port __rte_unused, uint16_t qidx __rte_unused,
|
||||
pkt_data = check_valid_packet(pkts[i]);
|
||||
|
||||
if (pkt_data == NULL) {
|
||||
rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1, "tx_calc_latency: ignoring invalid packet 0x%p.", (void*)pkts[i]);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_DEBUG, "tx_calc_latency: ignoring invalid packet %p.\n", (void*)pkts[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
pkt_data->srv_ts_tx = htonll(now);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "tx_calc_latency: tagged packet %p with %llu.\n", (void*)pkts[i], now);
|
||||
pkt_data->srv_ts_tx = rte_cpu_to_be_64(now);
|
||||
}
|
||||
|
||||
return nb_pkts;
|
||||
@ -80,32 +89,32 @@ locore_main(void * _unused __rte_unused)
|
||||
struct rte_ether_addr eth_addr;
|
||||
uint32_t core_id = rte_lcore_id();
|
||||
|
||||
if (rte_eth_dev_socket_id(options.s_portid) > 0 && rte_eth_dev_socket_id(options.s_portid) != (int)rte_socket_id()) {
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_WARNING, "locore_main: WARNING, port %d is on remote NUMA node to "
|
||||
"polling thread.\n\tPerformance will "
|
||||
"not be optimal.\n", options.s_portid);
|
||||
}
|
||||
|
||||
if (rte_eth_dev_socket_id(options.s_portid) > 0 && rte_eth_dev_socket_id(options.s_portid) != (int)rte_socket_id()) {
|
||||
rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1, "locore_main: WARNING, port %d is on remote NUMA node to "
|
||||
"polling thread.\n\tPerformance will "
|
||||
"not be optimal.\n", options.s_portid);
|
||||
}
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "locore_main: core %d running.\n", core_id);
|
||||
|
||||
rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "locore_main: core %d forwarding packets. [Ctrl+C to quit]\n", core_id);
|
||||
|
||||
while(1) {
|
||||
while(true) {
|
||||
uint16_t nb_tx = 0;
|
||||
const uint16_t nb_rx = rte_eth_rx_burst(options.s_portid, 0, bufs, BURST_SIZE);
|
||||
if (nb_rx == 0)
|
||||
continue;
|
||||
|
||||
if (nb_rx == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(int i = 0; i < nb_rx; i++) {
|
||||
|
||||
pkt_data = check_valid_packet(bufs[i]);
|
||||
|
||||
if (pkt_data == NULL) {
|
||||
rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1, "locore_main: core %d skipping invalid packet %p.", core_id, (void*)bufs[i]);
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_DEBUG, "locore_main: core %d skipping invalid packet %p.\n", core_id, (void*)bufs[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1,"locore_main: core %d rx packet from %x-%x-%x-%x-%x-%x", core_id,
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "locore_main: core %d rx packet %p from %x:%x:%x:%x:%x:%x\n", core_id, (void*)bufs[i],
|
||||
pkt_data->eth_hdr.s_addr.addr_bytes[0],
|
||||
pkt_data->eth_hdr.s_addr.addr_bytes[1],
|
||||
pkt_data->eth_hdr.s_addr.addr_bytes[2],
|
||||
@ -125,7 +134,7 @@ locore_main(void * _unused __rte_unused)
|
||||
const uint16_t nb_tx_succ = rte_eth_tx_burst(options.s_portid, 0, tx_bufs, nb_tx);
|
||||
// cleanup unsent packets
|
||||
if (nb_tx_succ < nb_tx) {
|
||||
rte_exit(EXIT_FAILURE, "locore_main: failed to send some packets.");
|
||||
rte_exit(EXIT_FAILURE, "locore_main: failed to send some packets.\n");
|
||||
// rte_log(RTE_LOG_WARNING, RTE_LOGTYPE_USER1,"locore_main: core %d some packets failed to queue to tx - expected: %d sent: %d", core_id, nb_tx, nb_tx_succ);
|
||||
// for (uint16_t buf = nb_tx_succ; buf < nb_tx; buf++)
|
||||
// rte_pktmbuf_free(tx_bufs[buf]);
|
||||
@ -139,12 +148,12 @@ static int
|
||||
port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
|
||||
{
|
||||
struct rte_eth_dev_info dev_info;
|
||||
struct rte_eth_conf port_conf;
|
||||
struct rte_eth_conf port_conf = port_conf_default;
|
||||
struct rte_eth_txconf txconf;
|
||||
struct rte_eth_rxconf rxconf;
|
||||
|
||||
uint16_t nb_rxd = RX_RING_SIZE;
|
||||
uint16_t nb_txd = TX_RING_SIZE;
|
||||
port_conf.rxmode.max_rx_pkt_len = RTE_ETHER_MAX_LEN;
|
||||
|
||||
if(!rte_eth_dev_is_valid_port(portid)) {
|
||||
return -1;
|
||||
@ -157,10 +166,7 @@ port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
|
||||
|
||||
if(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
|
||||
port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE;
|
||||
if(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)
|
||||
port_conf.txmode.offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM;
|
||||
if(dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM)
|
||||
port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_IPV4_CKSUM;
|
||||
port_conf.rxmode.max_rx_pkt_len = RTE_ETHER_MAX_LEN;
|
||||
|
||||
/* Configure the Ethernet device. */
|
||||
ret = rte_eth_dev_configure(portid, RX_RING_NUM, TX_RING_NUM, &port_conf);
|
||||
@ -172,8 +178,9 @@ port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
|
||||
return ret;
|
||||
|
||||
/* Allocate and set up 1 RX queue per Ethernet port. */
|
||||
rxconf = dev_info.default_rxconf;
|
||||
for (uint32_t i = 0; i < RX_RING_NUM; i++) {
|
||||
ret = rte_eth_rx_queue_setup(portid, i, nb_rxd, rte_eth_dev_socket_id(portid), NULL, mbuf_pool);
|
||||
ret = rte_eth_rx_queue_setup(portid, i, nb_rxd, rte_eth_dev_socket_id(portid), &rxconf, mbuf_pool);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@ -197,20 +204,14 @@ port_init(uint16_t portid, struct rte_mempool *mbuf_pool)
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
|
||||
" %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
|
||||
portid,
|
||||
addr.addr_bytes[0], addr.addr_bytes[1],
|
||||
addr.addr_bytes[2], addr.addr_bytes[3],
|
||||
addr.addr_bytes[4], addr.addr_bytes[5]);
|
||||
|
||||
/* Enable RX in promiscuous mode for the Ethernet device. */
|
||||
ret = rte_eth_promiscuous_enable(portid);
|
||||
ret = rte_eth_promiscuous_enable(portid);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
rte_eth_add_tx_callback(portid, 0, tx_calc_latency, NULL);
|
||||
rte_eth_add_rx_callback(portid, 0, rx_add_timestamp, NULL);
|
||||
if (rte_eth_add_tx_callback(portid, 0, tx_calc_latency, NULL) == NULL || rte_eth_add_rx_callback(portid, 0, rx_add_timestamp, NULL) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -230,21 +231,21 @@ int main(int argc, char* argv[])
|
||||
// init dpdk
|
||||
int ret = rte_eal_init(argc, argv);
|
||||
if (ret < 0) {
|
||||
rte_exit(EXIT_FAILURE, "rte_eal_init failed!");
|
||||
rte_exit(EXIT_FAILURE, "rte_eal_init failed!\n");
|
||||
}
|
||||
|
||||
argc -= ret;
|
||||
argv += ret;
|
||||
|
||||
// set warning level
|
||||
rte_log_set_level(RTE_LOGTYPE_USER1, RTE_LOG_WARNING);
|
||||
ntr_set_level(NTR_DEP_USER1, NTR_LEVEL_WARNING);
|
||||
{
|
||||
int c;
|
||||
// parse arguments
|
||||
while((c = getopt(argc, argv, "hv")) != -1) {
|
||||
switch (c) {
|
||||
case 'v':
|
||||
rte_log_set_level(RTE_LOGTYPE_USER1, RTE_LOG_INFO);
|
||||
ntr_set_level(NTR_DEP_USER1, ntr_get_level(NTR_DEP_USER1) + 1);
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
@ -259,31 +260,31 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
nb_ports = rte_eth_dev_count_avail();
|
||||
if (nb_ports < 2 || (nb_ports & 1)) {
|
||||
rte_exit(EXIT_FAILURE, "number of ports must be even");
|
||||
if (nb_ports == 0) {
|
||||
rte_exit(EXIT_FAILURE, "number of ports must be > 0\n");
|
||||
}
|
||||
|
||||
// create a mbuf memory pool on the socket
|
||||
mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", MBUF_MAX_COUNT * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
|
||||
if (mbuf_pool == nullptr) {
|
||||
rte_exit(EXIT_FAILURE, "cannot create mbuf pool");
|
||||
rte_exit(EXIT_FAILURE, "cannot create mbuf pool\n");
|
||||
}
|
||||
|
||||
uint16_t portid = rte_eth_find_next(0);
|
||||
if (portid == RTE_MAX_ETHPORTS) {
|
||||
rte_exit(EXIT_FAILURE, "cannot find an available port");
|
||||
rte_exit(EXIT_FAILURE, "cannot find an available port\n");
|
||||
}
|
||||
options.s_portid = portid;
|
||||
|
||||
if (port_init(portid, mbuf_pool) != 0) {
|
||||
rte_exit(EXIT_FAILURE, "cannot init port %d", portid);
|
||||
rte_exit(EXIT_FAILURE, "cannot init port %d\n", portid);
|
||||
}
|
||||
|
||||
if (rte_eth_macaddr_get(portid, &options.s_host_mac) != 0) {
|
||||
rte_exit(EXIT_FAILURE, "cannot get mac address of port %d", portid);
|
||||
rte_exit(EXIT_FAILURE, "cannot get mac address of port %d\n", portid);
|
||||
}
|
||||
|
||||
rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "Configured port %d with mac addr %x-%x-%x-%x-%x-%x", portid,
|
||||
ntr(NTR_DEP_USER1, NTR_LEVEL_INFO, "Configured port %d with mac addr %x:%x:%x:%x:%x:%x\n", portid,
|
||||
options.s_host_mac.addr_bytes[0],
|
||||
options.s_host_mac.addr_bytes[1],
|
||||
options.s_host_mac.addr_bytes[2],
|
||||
@ -293,13 +294,24 @@ int main(int argc, char* argv[])
|
||||
|
||||
|
||||
uint16_t lcore_id = rte_get_next_lcore(0, true, false);
|
||||
|
||||
if (lcore_id == RTE_MAX_LCORE) {
|
||||
rte_exit(EXIT_FAILURE, "cannot detect lcores.\n");
|
||||
}
|
||||
|
||||
if (rte_eal_remote_launch(locore_main, NULL, lcore_id) != 0) {
|
||||
rte_exit(EXIT_FAILURE, "failed to launch function on locore %d", lcore_id);
|
||||
rte_exit(EXIT_FAILURE, "failed to launch function on locore %d\n", lcore_id);
|
||||
}
|
||||
|
||||
// while(true) {
|
||||
// struct rte_eth_stats stats;
|
||||
// rte_eth_stats_get(portid, &stats);
|
||||
// printf("recv: %d missed: %d err: %d\n",(uint32_t)stats.ipackets, (uint32_t)stats.imissed,(uint32_t)stats.ierrors);
|
||||
// usleep(1000000);
|
||||
// }
|
||||
|
||||
if (rte_eal_wait_lcore(lcore_id) != 0) {
|
||||
rte_exit(EXIT_FAILURE, "failed to wait for locore %d", lcore_id);
|
||||
rte_exit(EXIT_FAILURE, "failed to wait for locore %d\n", lcore_id);
|
||||
}
|
||||
|
||||
// shouldn't get here
|
||||
|
Loading…
Reference in New Issue
Block a user