Commit 821d9418 authored by Joanne Hugé's avatar Joanne Hugé

Update XDP and add raw socket test, 600k PPS

parent 89c64f5e
...@@ -2,9 +2,9 @@ ecpri-tests/client ...@@ -2,9 +2,9 @@ ecpri-tests/client
ecpri-tests/server ecpri-tests/server
*.swp *.swp
*.swo *.swo
af-xdp/xdp_kern.ll af-xdp-test/af_xdp
af-xdp/xdp_kern.o af-xdp-test/af_xdp.d
af-xdp/xdp_user af-xdp-test/af_xdp.o
af-xdp/xdp_user.d raw-socket-test/raw_socket
af-xdp/xdp_user.o raw-socket-test/raw_socket.d
raw-socket-test/raw_socket.o
USER = xdp_user USER = af_xdp
KERN = xdp_kern LIBBPF = ${HOME}/ecpri/xdp/libbpf-build/usr
LIBBPF = ${HOME}/xdp/libbpf-build/usr
SRCDIR = "." SRCDIR = "."
SRCS = $(USER).c SRCS = $(USER).c
...@@ -22,18 +21,13 @@ CFLAGS += -I $(LIBBPF)/include ...@@ -22,18 +21,13 @@ CFLAGS += -I $(LIBBPF)/include
vpath %.c $(SRCDIR) vpath %.c $(SRCDIR)
$(USER): $(OBJS) xdp_kern.o $(USER): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@ $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@
xdp_kern.o: $(KERN).c
clang $(IFLAGS) -isystem $(LIBBPF)/include -S -target bpf -D __BPF_TRACING__ -Wall -O2 -emit-llvm -c -g -o $(KERN).ll $^
llc -march=bpf -filetype=obj -o $@ $(KERN).ll
-include $(subst .c,.d,$(SRCS)) -include $(subst .c,.d,$(SRCS))
clean: clean:
$(RM) -rf bin $(RM) -rf bin
$(RM) $(OBJS) $(USER) $(subst .c,.d,$(SRCS)) $(RM) $(OBJS) $(USER) $(subst .c,.d,$(SRCS))
$(RM) -rf xdp_kern.o $(KERN).ll
.PHONY: clean .PHONY: clean
...@@ -50,10 +50,10 @@ ...@@ -50,10 +50,10 @@
//#define FRAME_SIZE XSK_UMEM__DEFAULT_FRAME_SIZE //#define FRAME_SIZE XSK_UMEM__DEFAULT_FRAME_SIZE
#define FRAME_SIZE 2048 #define FRAME_SIZE 2048
#define PACKET_SIZE 262 #define PACKET_SIZE 262
//#define NB_PACKETS 1000000 #define NB_PACKETS 1000000
#define NB_PACKETS 100 //#define NB_PACKETS 100
#define BATCH_SIZE 2048 #define BATCH_SIZE 2048
#define PRINT_PROGRESS //#define PRINT_PROGRESS
#define PRINT_PROGRESS_INTERVAL 1000 #define PRINT_PROGRESS_INTERVAL 1000
//#define DEBUG //#define DEBUG
......
...@@ -11,7 +11,7 @@ tx_packets() { ...@@ -11,7 +11,7 @@ tx_packets() {
xdp_off; xdp_off;
make clean && make; make clean && make;
A=$(tx_packets) A=$(tx_packets)
nice -n -20 chrt 99 ./xdp_user; nice -n -20 chrt 99 ./af_xdp;
B=$(tx_packets) B=$(tx_packets)
echo "Ethtool tx packets sent: $((B -A))"; echo "Ethtool tx packets sent: $((B -A))";
xdp_off; xdp_off;
#define KBUILD_MODNAME "blub"
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/if_link.h>
#include <linux/if_xdp.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/udp.h>
//#include "/root/xdp/libbpf-build/usr/include/bpf/bpf_helpers.h"
//#include "/root/xdp/libbpf-build/usr/include/bpf/bpf_endian.h"
#include "bpf/bpf_helpers.h"
#include "bpf/bpf_endian.h"
//#include <bpf/bpf_helpers.h>
//#include <bpf/bpf_endian.h>
struct bpf_map_def SEC("maps") xsks_map = {
.type = BPF_MAP_TYPE_XSKMAP,
.key_size = sizeof(int),
.value_size = sizeof(int),
.max_entries = 64,
};
SEC("xdp_sock")
int xdp_sock_prog(struct xdp_md *ctx)
{
int index;
index = ctx->rx_queue_index;
/* If socket bound to rx_queue then redirect to user space */
if (bpf_map_lookup_elem(&xsks_map, &index))
return bpf_redirect_map(&xsks_map, index, 0);
/* Else pass to Linux' network stack */
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";
CC=gcc
CFLAGS=-O2
CFLAGS+=-g
PROG=raw_packet
OBJ=$(PROG).o
all: $(PROG)
clean:
rm -f $(PROG) *.o *~
$(PROG): $(OBJ)
$(CC) $(LDFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $^
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <getopt.h>
#include <immintrin.h>
#include <inttypes.h>
#include <limits.h>
#include <linux/if_packet.h>
#include <math.h>
#include <netdb.h>
#include <netinet/ether.h>
#include <netinet/in.h>
#include <net/if.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
static void log_error(const char * section, const char * msg, ...) {
time_t t;
struct tm ts;
char line[256];
va_list arglist;
time(&t);
ts = *localtime(&t);
strftime(line, 80, "%m-%d %H:%M:%S", &ts);
sprintf(line + strlen(line), " ERROR [%s] ", section);
va_start(arglist, msg);
vsprintf(line + strlen(line), msg, arglist);
va_end(arglist);
puts(line);
exit(EXIT_FAILURE);
}
static void log_info(const char * section, const char * msg, ...) {
time_t t;
struct tm ts;
char line[256];
va_list arglist;
time(&t);
ts = *localtime(&t);
strftime(line, 80, "%m-%d %H:%M:%S", &ts);
sprintf(line + strlen(line), " INFO [%s] ", section);
va_start(arglist, msg);
vsprintf(line + strlen(line), msg, arglist);
va_end(arglist);
puts(line);
}
static int latency_target_fd = -1;
static int32_t latency_target_value = 0;
void set_latency_target(void) {
struct stat s;
int err;
errno = 0;
err = stat("/dev/cpu_dma_latency", &s);
if (err == -1) {
error(EXIT_FAILURE, errno, "WARN: stat /dev/cpu_dma_latency failed");
return;
}
errno = 0;
latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR);
if (latency_target_fd == -1) {
error(EXIT_FAILURE, errno, "WARN: open /dev/cpu_dma_latency");
return;
}
errno = 0;
err = write(latency_target_fd, &latency_target_value, 4);
if (err < 1) {
error(EXIT_FAILURE, errno, "# error setting cpu_dma_latency to %d!",
latency_target_value);
close(latency_target_fd);
return;
}
printf("# /dev/cpu_dma_latency set to %dus\n", latency_target_value);
}
// Counters
static volatile int64_t sent_frame_count;
// Network
static int send_sockfd;
static struct sockaddr_ll connect_sk_addr;
// Timestamps utils
#define NSEC_PER_SEC INT64_C(1000000000)
static struct timespec int_to_ts(int64_t t) {
struct timespec ts;
ts.tv_sec = t / NSEC_PER_SEC;
ts.tv_nsec = t - (ts.tv_sec * NSEC_PER_SEC);
return ts;
}
static int64_t ts_to_int(struct timespec ts) {
return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
}
static void add_ns(struct timespec *t, int64_t ns) {
t->tv_nsec += ns;
while (t->tv_nsec >= ((int64_t)NSEC_PER_SEC)) {
t->tv_sec += 1;
t->tv_nsec -= NSEC_PER_SEC;
}
}
static int64_t calcdiff_ns(struct timespec t1, struct timespec t2) {
int64_t diff;
diff = NSEC_PER_SEC * ((int)t1.tv_sec - (int)t2.tv_sec);
diff += ((int)t1.tv_nsec - (int)t2.tv_nsec);
return diff;
}
#define PACKET_SIZE 262
#define NB_PACKETS 2000000
int main() {
uint8_t dst_mac[6] = "\xb8\x59\x9f\x07\x7d\xdb";
uint8_t src_mac[6] = "\x04\x09\xa5\x0f\x9f\x4c";
char * network_if = "ens9f1np1";
uint8_t packet[PACKET_SIZE];
uint8_t buffer[PACKET_SIZE * 1024];
struct ether_header *eh = (struct ether_header *) packet;
int if_index;
struct timespec initial, end;
int64_t sent;
int64_t duration_ns;
int k = 0;
struct mmsghdr msgh[1024];
struct iovec msgv[1024];
//set_latency_target();
memset((uint8_t *) packet, 0, PACKET_SIZE);
if (!(if_index = if_nametoindex(network_if))) {
perror("if_nametoindex");
return 1;
}
if ((send_sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
perror("Socket Error");
return 1;
}
connect_sk_addr.sll_ifindex = if_index;
connect_sk_addr.sll_halen = ETH_ALEN;
for(int i = 0; i < 6; i++)
connect_sk_addr.sll_addr[i] = dst_mac[i];
for(int i = 0; i < 6; i++)
eh->ether_shost[i] = src_mac[i];
for(int i = 0; i < 6; i++)
eh->ether_dhost[i] = dst_mac[i];
/* Ethertype field */
eh->ether_type = htons(0xaefe);
for(int i = 0; i < 1024; i++)
memcpy(buffer + (i * PACKET_SIZE), packet, PACKET_SIZE);
memset(msgv, 0, sizeof(msgv));
memset(msgh, 0, sizeof(msgh));
for(int j = 0; j < 1024; j++) {
msgh[j].msg_hdr.msg_name = &connect_sk_addr;
msgh[j].msg_hdr.msg_namelen = sizeof(connect_sk_addr);
msgh[j].msg_hdr.msg_iov = &msgv[j];
msgh[j].msg_hdr.msg_iovlen = 1;
}
for(int j = 0; j < 1024; j++) {
msgv[j].iov_base = buffer + (j * PACKET_SIZE);
msgv[j].iov_len = PACKET_SIZE;
}
clock_gettime(CLOCK_TAI, &initial);
for(int i = 0; sent < NB_PACKETS; i++) {
int ret = sendmmsg(send_sockfd, msgh, 1024, 0);
if(ret < 1024)
error(EXIT_FAILURE, errno, "sendmmsg error (returned %d)", ret);
sent += ret;
}
clock_gettime(CLOCK_TAI, &end);
duration_ns = calcdiff_ns(end, initial);
log_info("STATS", "Duration: %" PRIi64 " us", duration_ns / 1000);
log_info("STATS", "Packets sent: %" PRIi64 " / %" PRIi64, sent, NB_PACKETS);
log_info("STATS", "pps: %" PRIi64, (sent * NSEC_PER_SEC) / duration_ns);
return 0;
}
#!/bin/bash
set -e
tx_packets() {
ethtool -S ens9f1np1|grep -v ": 0"|grep "tx_packets:"|awk '{print $2;}';
}
make clean && make;
A=$(tx_packets)
nice -n -20 chrt 99 ./raw_packet;
B=$(tx_packets)
echo "Ethtool tx packets sent: $((B -A))";
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