Commit e0a5463d authored by Leonardo Lai's avatar Leonardo Lai

update pktgen and default values

parent b53ab6ba
...@@ -5,4 +5,5 @@ Receiver: ...@@ -5,4 +5,5 @@ Receiver:
sudo ./pktgen -c ../../config.ini -f recv sudo ./pktgen -c ../../config.ini -f recv
Note: '-l' is the length of the whole frame, including MAC, IPv4 and UDP headers Note: '-l' is the UDP payload length, excluding the MAC, IPv4 and UDP headers
If you want to include them in the stats, add the '-h' option.
...@@ -6,19 +6,22 @@ ...@@ -6,19 +6,22 @@
// -f <func> : function ('send' or 'recv') // -f <func> : function ('send' or 'recv')
// //
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <time.h> #include <time.h>
#include <arpa/inet.h> #include <unistd.h>
#include <netinet/in.h>
#include <udpdk_api.h> #include <udpdk_api.h>
#define BUSYWAIT
#define PORT_SEND 10000 #define PORT_SEND 10000
#define PORT_RECV 10001 #define PORT_RECV 10001
#define IP_RECV "172.31.100.1" #define IP_RECV "172.31.100.1"
...@@ -27,6 +30,11 @@ ...@@ -27,6 +30,11 @@
#define IP_HDR_LEN 20 #define IP_HDR_LEN 20
#define UDP_HDR_LEN 8 #define UDP_HDR_LEN 8
typedef struct stats_t {
uint64_t bytes_sent;
uint64_t bytes_recv;
} stats_t;
const char mydata[2048] = { const char mydata[2048] = {
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam varius semper faucibus. Vivamus consectetur pharetra massa. Nam at tellus semper, eleifend tellus elementum, pulvinar odio. Ut accumsan ligula ac ex rhoncus, nec pretium urna pharetra. Suspendisse potenti. Duis vel enim vel tellus dictum vehicula eu vitae elit. Etiam at lacus varius diam rutrum accumsan quis sed velit. Nulla tortor mi, congue sit amet malesuada sit amet, pellentesque ac mi. Nunc feugiat mi vitae turpis elementum maximus. Sed malesuada mi ac rhoncus condimentum. Nunc venenatis, libero a pharetra molestie, risus orci tempus arcu, sit amet molestie ipsum purus ac urna. Nunc nec ligula massa. Aenean ut libero ut erat tincidunt aliquet." "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam varius semper faucibus. Vivamus consectetur pharetra massa. Nam at tellus semper, eleifend tellus elementum, pulvinar odio. Ut accumsan ligula ac ex rhoncus, nec pretium urna pharetra. Suspendisse potenti. Duis vel enim vel tellus dictum vehicula eu vitae elit. Etiam at lacus varius diam rutrum accumsan quis sed velit. Nulla tortor mi, congue sit amet malesuada sit amet, pellentesque ac mi. Nunc feugiat mi vitae turpis elementum maximus. Sed malesuada mi ac rhoncus condimentum. Nunc venenatis, libero a pharetra molestie, risus orci tempus arcu, sit amet molestie ipsum purus ac urna. Nunc nec ligula massa. Aenean ut libero ut erat tincidunt aliquet."
"Praesent consequat, dui nec pellentesque dapibus, lorem orci placerat sem, consectetur egestas metus lacus eu purus. Sed scelerisque, lorem nec euismod laoreet, sem tellus tincidunt lorem, eu faucibus tortor massa at sapien. Maecenas commodo consectetur leo, non rhoncus sem ullamcorper ut. Proin in purus quis ante posuere rutrum sed ut nisl. Etiam pretium egestas purus sed egestas. Vivamus ut suscipit neque. Donec eleifend magna ut mauris pellentesque, ut lobortis neque pharetra. Phasellus vel erat condimentum diam vulputate rhoncus nec eu lacus. Suspendisse condimentum, magna eu pulvinar porta, nisi ligula accumsan urna, a suscipit turpis ex a elit. Proin ipsum dolor, ultrices at luctus eu, sagittis ac ligula." "Praesent consequat, dui nec pellentesque dapibus, lorem orci placerat sem, consectetur egestas metus lacus eu purus. Sed scelerisque, lorem nec euismod laoreet, sem tellus tincidunt lorem, eu faucibus tortor massa at sapien. Maecenas commodo consectetur leo, non rhoncus sem ullamcorper ut. Proin in purus quis ante posuere rutrum sed ut nisl. Etiam pretium egestas purus sed egestas. Vivamus ut suscipit neque. Donec eleifend magna ut mauris pellentesque, ut lobortis neque pharetra. Phasellus vel erat condimentum diam vulputate rhoncus nec eu lacus. Suspendisse condimentum, magna eu pulvinar porta, nisi ligula accumsan urna, a suscipit turpis ex a elit. Proin ipsum dolor, ultrices at luctus eu, sagittis ac ligula."
...@@ -37,19 +45,60 @@ typedef enum {SEND, RECV} app_mode; ...@@ -37,19 +45,60 @@ typedef enum {SEND, RECV} app_mode;
static app_mode mode = SEND; static app_mode mode = SEND;
static int pktlen = 64; static int pktlen = 64;
static volatile int app_alive = 1; static bool hdr_stats = false;
static bool dump = false;
static uint64_t tx_rate = 0;
static struct timespec tx_period;
static volatile bool app_alive = true;
static const char *progname; static const char *progname;
static void signal_handler(int signum) static void signal_handler(int signum)
{ {
printf("Caught signal %d in sendrecv main process\n", signum); printf("Caught signal %d in sendrecv main process\n", signum);
udpdk_interrupt(signum); udpdk_interrupt(signum);
app_alive = 0; app_alive = false;
} }
static void send_body(void) static inline struct timespec timespec_add(struct timespec a, struct timespec b)
{
struct timespec ret = { a.tv_sec + b.tv_sec, a.tv_nsec + b.tv_nsec };
if (ret.tv_nsec >= 1000000000) {
ret.tv_sec++;
ret.tv_nsec -= 1000000000;
}
return ret;
}
static inline struct timespec timespec_sub(struct timespec a, struct timespec b)
{
struct timespec ret = { a.tv_sec - b.tv_sec, a.tv_nsec - b.tv_nsec };
if (ret.tv_nsec < 0) {
ret.tv_sec--;
ret.tv_nsec += 1000000000;
}
return ret;
}
static struct timespec wait_time(struct timespec ts)
{
#ifdef BUSYWAIT
for (;;) {
struct timespec w, cur;
clock_gettime(CLOCK_REALTIME, &cur);
w = timespec_sub(ts, cur);
if (w.tv_sec < 0)
return cur;
}
#else
while (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL) != 0);
return ts;
#endif
}
static void send_body(stats_t *stats)
{ {
struct sockaddr_in servaddr, destaddr; struct sockaddr_in servaddr, destaddr;
struct timespec t_next;
int n; int n;
printf("SEND mode\n"); printf("SEND mode\n");
...@@ -70,22 +119,43 @@ static void send_body(void) ...@@ -70,22 +119,43 @@ static void send_body(void)
return; return;
} }
printf(("Entering send loop\n")); tx_period.tv_sec = tx_period.tv_nsec = 0;
if (tx_rate > 0) {
uint64_t x = (uint64_t)1000000000 / (uint64_t)tx_rate;
tx_period.tv_nsec = x;
tx_period.tv_sec = tx_period.tv_nsec / 1000000000;
tx_period.tv_nsec = tx_period.tv_nsec % 1000000000;
clock_gettime(CLOCK_REALTIME, &t_next);
}
printf("Entering send loop\n");
printf("Sending a packet every %ld.%09ld s\n", tx_period.tv_sec, tx_period.tv_nsec);
while (app_alive) { while (app_alive) {
int ret;
// Wait for the right moment to send the packet
if (tx_rate > 0) {
t_next = timespec_add(t_next, tx_period);
wait_time(t_next);
}
// Send packet // Send packet
destaddr.sin_family = AF_INET; destaddr.sin_family = AF_INET;
destaddr.sin_addr.s_addr = inet_addr(IP_RECV); destaddr.sin_addr.s_addr = inet_addr(IP_RECV);
destaddr.sin_port = htons(PORT_RECV); destaddr.sin_port = htons(PORT_RECV);
udpdk_sendto(sock, (void *)mydata, pktlen - ETH_HDR_LEN - IP_HDR_LEN - UDP_HDR_LEN, 0, ret = udpdk_sendto(sock, (void *)mydata, pktlen, 0,
(const struct sockaddr *) &destaddr, sizeof(destaddr)); (const struct sockaddr *) &destaddr, sizeof(destaddr));
if (ret > 0) {
// TODO rate stats->bytes_sent += ret;
sleep(1); if (hdr_stats) {
stats->bytes_sent += ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN;
}
}
} }
} }
static void recv_body(void) static void recv_body(stats_t *stats)
{ {
int sock, n; int sock, n;
struct sockaddr_in servaddr, cliaddr; struct sockaddr_in servaddr, cliaddr;
...@@ -96,7 +166,7 @@ static void recv_body(void) ...@@ -96,7 +166,7 @@ static void recv_body(void)
// Create a socket // Create a socket
if ((sock = udpdk_socket(AF_INET, SOCK_DGRAM, 0)) < 0) { if ((sock = udpdk_socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "Pong: socket creation failed"); fprintf(stderr, "Recv: socket creation failed");
return; return;
} }
// Bind it // Bind it
...@@ -106,7 +176,7 @@ static void recv_body(void) ...@@ -106,7 +176,7 @@ static void recv_body(void)
servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT_RECV); servaddr.sin_port = htons(PORT_RECV);
if (udpdk_bind(sock, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { if (udpdk_bind(sock, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
fprintf(stderr, "Pong: bind failed"); fprintf(stderr, "Recv: bind failed");
return; return;
} }
...@@ -116,20 +186,29 @@ static void recv_body(void) ...@@ -116,20 +186,29 @@ static void recv_body(void)
int len = sizeof(cliaddr); int len = sizeof(cliaddr);
n = udpdk_recvfrom(sock, (void *)buf, 2048, 0, ( struct sockaddr *) &cliaddr, &len); n = udpdk_recvfrom(sock, (void *)buf, 2048, 0, ( struct sockaddr *) &cliaddr, &len);
if (n > 0) { if (n > 0) {
buf[n] = '\0'; stats->bytes_recv += n;
printf("Received payload of %d bytes from %s port %d:\n%s\n", n, if (hdr_stats) {
stats->bytes_recv += ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN;
}
if (dump) {
buf[n] = '\0';
printf("Received payload of %d bytes from %s port %d:\n%s\n", n,
inet_ntop(AF_INET,&cliaddr.sin_addr, clientname, sizeof(clientname)), inet_ntop(AF_INET,&cliaddr.sin_addr, clientname, sizeof(clientname)),
ntohs(cliaddr.sin_port), buf); ntohs(cliaddr.sin_port), buf);
}
} }
} }
} }
static void usage(void) static void usage(void)
{ {
printf("%s -c CONFIG -f FUNCTION \n" printf("%s -c CONFIG -f FUNCTION [-r RATE] [-l LEN] [-h] [-d] \n"
" -c CONFIG: .ini configuration file" " -c CONFIG: .ini configuration file"
" -f FUNCTION: 'send' or 'recv'\n" " -f FUNCTION: 'send' or 'recv'\n"
" -l LEN: packet length (including 42 bytes for ETH, IPv4 and UDP headers)\n" " -r RATE: desired transmission rate in bytes"
" -l LEN: payload length\n"
" -h consider also the MAC, IPv4 and UDP headers bytes for tx_rate and stats\n"
" -d dump the payload (ASCII)\n"
, progname); , progname);
} }
...@@ -140,7 +219,7 @@ static int parse_app_args(int argc, char *argv[]) ...@@ -140,7 +219,7 @@ static int parse_app_args(int argc, char *argv[])
progname = argv[0]; progname = argv[0];
while ((c = getopt(argc, argv, "c:f:l:")) != -1) { while ((c = getopt(argc, argv, "c:f:r:l:hd")) != -1) {
switch (c) { switch (c) {
case 'c': case 'c':
// this is for the .ini cfg file needed by DPDK, not by the app // this is for the .ini cfg file needed by DPDK, not by the app
...@@ -155,9 +234,18 @@ static int parse_app_args(int argc, char *argv[]) ...@@ -155,9 +234,18 @@ static int parse_app_args(int argc, char *argv[])
return -1; return -1;
} }
break; break;
case 'r':
tx_rate = atoi(optarg);
break;
case 'l': case 'l':
pktlen = atoi(optarg); pktlen = atoi(optarg);
break; break;
case 'h':
hdr_stats = true;
break;
case 'd':
dump = true;
break;
default: default:
fprintf(stderr, "Unknown option `-%c'.\n", optopt); fprintf(stderr, "Unknown option `-%c'.\n", optopt);
usage(); usage();
...@@ -167,8 +255,28 @@ static int parse_app_args(int argc, char *argv[]) ...@@ -167,8 +255,28 @@ static int parse_app_args(int argc, char *argv[])
return 0; return 0;
} }
static void reset_stats(stats_t *stats)
{
stats->bytes_sent = 0;
stats->bytes_recv = 0;
}
static void *stats_routine(void *arg)
{
stats_t *stats = (stats_t *)arg;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
while (1) {
printf("Sent: %ld bps | Recv: %ld bps\n", stats->bytes_sent, stats->bytes_recv);
sleep(1);
}
return NULL;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
pthread_t stats_thr;
stats_t stats;
int retval; int retval;
// Register signals for shutdown // Register signals for shutdown
...@@ -192,14 +300,24 @@ int main(int argc, char *argv[]) ...@@ -192,14 +300,24 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
// Start the thread to visualize statistics in real time
reset_stats(&stats);
if (pthread_create(&stats_thr, NULL, stats_routine, &stats)) {
fprintf(stderr, "Error creating thread\n");
return -1;
}
if (mode == SEND) { if (mode == SEND) {
send_body(); send_body(&stats);
} else { } else {
recv_body(); recv_body(&stats);
} }
pktgen_end: pktgen_end:
// Halt the stats thread
pthread_cancel(stats_thr);
pthread_join(stats_thr, NULL);
// Cleanup
udpdk_interrupt(0); udpdk_interrupt(0);
udpdk_cleanup(); udpdk_cleanup();
return 0; return 0;
......
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
#define PORT_TX 0 #define PORT_TX 0
#define QUEUE_RX 0 #define QUEUE_RX 0
#define QUEUE_TX 0 #define QUEUE_TX 0
#define NUM_RX_DESC_DEFAULT 1024 #define NUM_RX_DESC_DEFAULT 2048
#define NUM_TX_DESC_DEFAULT 1024 #define NUM_TX_DESC_DEFAULT 2048
#define MBUF_CACHE_SIZE 512 #define MBUF_CACHE_SIZE 512
#define PKTMBUF_POOL_RX_NAME "UDPDK_mbuf_pool_RX" #define PKTMBUF_POOL_RX_NAME "UDPDK_mbuf_pool_RX"
#define PKTMBUF_POOL_TX_NAME "UDPDK_mbuf_pool_TX" #define PKTMBUF_POOL_TX_NAME "UDPDK_mbuf_pool_TX"
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
/* Exchange memzone */ /* Exchange memzone */
#define EXCH_MEMZONE_NAME "UDPDK_exchange_desc" #define EXCH_MEMZONE_NAME "UDPDK_exchange_desc"
#define EXCH_SLOTS_NAME "UDPDK_exchange_slots" #define EXCH_SLOTS_NAME "UDPDK_exchange_slots"
#define EXCH_RING_SIZE 128 #define EXCH_RING_SIZE 2048
#define EXCH_RX_RING_NAME "UDPDK_exchange_ring_%u_RX" #define EXCH_RX_RING_NAME "UDPDK_exchange_ring_%u_RX"
#define EXCH_TX_RING_NAME "UDPDK_exchange_ring_%u_TX" #define EXCH_TX_RING_NAME "UDPDK_exchange_ring_%u_TX"
#define EXCH_BUF_SIZE 32 #define EXCH_BUF_SIZE 32
......
...@@ -105,7 +105,6 @@ static int init_mbuf_pools(void) ...@@ -105,7 +105,6 @@ static int init_mbuf_pools(void)
/* Initialize a DPDK port */ /* Initialize a DPDK port */
static int init_port(uint16_t port_num) static int init_port(uint16_t port_num)
{ {
// TODO add support for multiple rings
const struct rte_eth_conf port_conf = { const struct rte_eth_conf port_conf = {
.rxmode = { .rxmode = {
.mq_mode = ETH_MQ_RX_RSS, .mq_mode = ETH_MQ_RX_RSS,
...@@ -119,6 +118,7 @@ static int init_port(uint16_t port_num) ...@@ -119,6 +118,7 @@ static int init_port(uint16_t port_num)
.offloads = DEV_TX_OFFLOAD_MULTI_SEGS, .offloads = DEV_TX_OFFLOAD_MULTI_SEGS,
} }
}; };
// TODO add RSS support
const uint16_t rx_rings = 1; const uint16_t rx_rings = 1;
const uint16_t tx_rings = 1; const uint16_t tx_rings = 1;
uint16_t rx_ring_size = NUM_RX_DESC_DEFAULT; uint16_t rx_ring_size = NUM_RX_DESC_DEFAULT;
......
...@@ -357,7 +357,8 @@ ssize_t udpdk_sendto(int sockfd, const void *buf, size_t len, int flags, ...@@ -357,7 +357,8 @@ ssize_t udpdk_sendto(int sockfd, const void *buf, size_t len, int flags,
// Put the packet in the tx_ring // Put the packet in the tx_ring
if (rte_ring_enqueue(exch_slots[sockfd].tx_q, (void *)pkt) < 0) { if (rte_ring_enqueue(exch_slots[sockfd].tx_q, (void *)pkt) < 0) {
RTE_LOG(ERR, SYSCALL, "Sendto failed to put packet in the TX ring\n"); RTE_LOG(ERR, SYSCALL, "Sendto failed to put packet in the TX ring\n Total: %d Free: %d\n",
rte_ring_count(exch_slots[sockfd].tx_q), rte_ring_free_count(exch_slots[sockfd].tx_q));
errno = ENOBUFS; errno = ENOBUFS;
rte_pktmbuf_free(pkt); rte_pktmbuf_free(pkt);
return -1; return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment