Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
trx-ecpri
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
trx-ecpri
Commits
5a937ca2
Commit
5a937ca2
authored
Oct 01, 2021
by
Joanne Hugé
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add AF_XDP test program
parent
7f143fbf
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
385 additions
and
0 deletions
+385
-0
.gitignore
.gitignore
+6
-0
af-xdp/Makefile
af-xdp/Makefile
+39
-0
af-xdp/xdp_kern.c
af-xdp/xdp_kern.c
+39
-0
af-xdp/xdp_user.c
af-xdp/xdp_user.c
+301
-0
No files found.
.gitignore
View file @
5a937ca2
...
@@ -2,3 +2,9 @@ ecpri-tests/client
...
@@ -2,3 +2,9 @@ ecpri-tests/client
ecpri-tests/server
ecpri-tests/server
*.swp
*.swp
*.swo
*.swo
af-xdp/xdp_kern.ll
af-xdp/xdp_kern.o
af-xdp/xdp_user
af-xdp/xdp_user.d
af-xdp/xdp_user.o
af-xdp/Makefile
0 → 100644
View file @
5a937ca2
USER
=
xdp_user
KERN
=
xdp_kern
LIBBPF
=
${HOME}
/xdp/libbpf-build/usr
SRCDIR
=
"."
SRCS
=
$(USER)
.c
OBJS
=
$(SRCS:%.c=%.o)
ifeq
($(DEBUG),)
CFLAGS
=
-O2
else
CFLAGS
=
-Og
-g
-Wall
-Wextra
endif
CFLAGS
+=
-MD
-MP
CFLAGS
+=
-I
$(SRCDIR)
CFLAGS
+=
-std
=
gnu99
LDFLAGS
+=
-pthread
-L
$(LIBBPF)
/lib64
-l
:libbpf.a
-lelf
-lz
CFLAGS
+=
-I
$(LIBBPF)
/include
vpath
%.c
$(SRCDIR)
$(USER)
:
$(OBJS) xdp_kern.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))
clean
:
$(RM)
-rf
bin
$(RM)
$(OBJS)
$(USER)
$(
subst
.c,.d,
$(SRCS)
)
$(RM)
-rf
xdp_kern.o
$(KERN)
.ll
.PHONY
:
clean
af-xdp/xdp_kern.c
0 → 100644
View file @
5a937ca2
#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"
;
af-xdp/xdp_user.c
0 → 100644
View file @
5a937ca2
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <getopt.h>
#include <ifaddrs.h>
#include <inttypes.h>
#include <limits.h>
#include <linux/errqueue.h>
#include <linux/ethtool.h>
#include <linux/net_tstamp.h>
#include <linux/sockios.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <signal.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/types.h>
#include <time.h>
#include <unistd.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <bpf/xsk.h>
#include <linux/if_ether.h>
#include <linux/if_link.h>
#include <linux/if_xdp.h>
#include <linux/ip.h>
#include <linux/udp.h>
#define err(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
exit(EXIT_FAILURE); \
} while (0)
#define err_errno(...) error(EXIT_FAILURE, errno, __VA_ARGS__);
#define NUM_FRAMES 4096
#define ETH_FCS_SIZE 4
#define FRAME_SIZE XSK_UMEM__DEFAULT_FRAME_SIZE
#define PACKET_SIZE 64
#define DEBUG
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
);
}
#ifdef DEBUG
static
void
log_debug
(
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
),
" DEBUG [%s] "
,
section
);
va_start
(
arglist
,
msg
);
vsprintf
(
line
+
strlen
(
line
),
msg
,
arglist
);
va_end
(
arglist
);
puts
(
line
);
}
#else
#define log_debug(...)
#endif
struct
xsk_umem_info
{
struct
xsk_ring_prod
fq
;
struct
xsk_ring_cons
cq
;
struct
xsk_umem
*
umem
;
void
*
buffer
;
};
struct
xdpsock
{
struct
xsk_ring_cons
rx
;
struct
xsk_ring_prod
tx
;
struct
xsk_umem_info
umem
;
struct
xsk_socket
*
xsk
;
int
fd
;
};
static
void
init_xdp_recv
(
char
*
network_if
);
static
void
init_xdp_send
(
char
*
network_if
);
static
int
recv_xdp_packet
(
void
);
static
void
init_recv
(
void
);
static
void
send_xdp_packet
(
void
);
static
void
recv_xdp_cleanup
(
void
);
static
void
close_xdp_socket
(
void
);
static
uint8_t
pkt_data
[
XSK_UMEM__DEFAULT_FRAME_SIZE
];
static
struct
xdpsock
send_xdp_socket
;
static
struct
xdpsock
recv_xdp_socket
;
static
int
received
;
static
uint32_t
idx_rx
=
0
,
idx_recv
;
int
main
()
{
char
*
network_if
=
"ens9f1np1"
;
log_info
(
""
,
"Starting"
);
init_xdp_send
(
network_if
);
//init_xdp_recv(network_if);
return
0
;
}
static
void
init_xdp_send
(
char
*
network_if
)
{
uint32_t
idx
;
int
ret
,
i
,
xsks_map
=
0
;
int
batch_size
;
struct
xsk_socket_config
xsk_cfg
;
struct
xsk_umem_config
cfg
=
{
.
fill_size
=
XSK_RING_PROD__DEFAULT_NUM_DESCS
,
.
comp_size
=
XSK_RING_CONS__DEFAULT_NUM_DESCS
,
.
frame_size
=
FRAME_SIZE
,
.
frame_headroom
=
XSK_UMEM__DEFAULT_FRAME_HEADROOM
,
.
flags
=
0
,
};
void
*
buffer
=
NULL
;
struct
ethhdr
*
eth_hdr
=
(
struct
ethhdr
*
)
pkt_data
;
memcpy
(
eth_hdr
->
h_dest
,
"
\xb8\x59\x9f\x07\x7d\xdb
"
,
ETH_ALEN
);
memcpy
(
eth_hdr
->
h_source
,
"
\x04\x09\xa5\x0f\x9f\x4c
"
,
ETH_ALEN
);
eth_hdr
->
h_proto
=
htons
(
ETH_P_IP
);
log_debug
(
""
,
"posix_memalign"
);
/* Allocate user space memory for xdp frames */
ret
=
posix_memalign
(
&
buffer
,
sysconf
(
_SC_PAGE_SIZE
),
NUM_FRAMES
*
FRAME_SIZE
);
if
(
ret
)
err_errno
(
"posix_memalign() failed"
);
log_debug
(
""
,
"xsk_umem__create"
);
ret
=
xsk_umem__create
(
&
send_xdp_socket
.
umem
.
umem
,
buffer
,
NUM_FRAMES
*
FRAME_SIZE
,
&
send_xdp_socket
.
umem
.
fq
,
&
send_xdp_socket
.
umem
.
cq
,
&
cfg
);
if
(
ret
)
err
(
"xsk_umem__create() failed"
);
send_xdp_socket
.
umem
.
buffer
=
buffer
;
log_debug
(
""
,
"open_xdp_socket"
);
/* Create XDP socket */
xsk_cfg
.
rx_size
=
XSK_RING_CONS__DEFAULT_NUM_DESCS
;
xsk_cfg
.
tx_size
=
XSK_RING_PROD__DEFAULT_NUM_DESCS
;
xsk_cfg
.
libbpf_flags
=
0
;
xsk_cfg
.
xdp_flags
=
XDP_FLAGS_DRV_MODE
;
xsk_cfg
.
bind_flags
=
0
;
log_debug
(
""
,
"xsk_socket__create"
);
ret
=
xsk_socket__create
(
&
send_xdp_socket
.
xsk
,
network_if
,
0
,
send_xdp_socket
.
umem
.
umem
,
&
send_xdp_socket
.
rx
,
&
send_xdp_socket
.
tx
,
&
xsk_cfg
);
log_debug
(
""
,
"send_xdp_packet"
);
send_xdp_packet
();
}
static
void
init_xdp_recv
(
char
*
network_if
)
{
uint32_t
idx
;
int
ret
,
i
,
xsks_map
=
0
;
int
batch_size
;
struct
xsk_socket_config
xsk_cfg
;
struct
xsk_umem_config
cfg
=
{
.
fill_size
=
XSK_RING_PROD__DEFAULT_NUM_DESCS
,
.
comp_size
=
XSK_RING_CONS__DEFAULT_NUM_DESCS
,
.
frame_size
=
FRAME_SIZE
,
.
frame_headroom
=
XSK_UMEM__DEFAULT_FRAME_HEADROOM
,
.
flags
=
0
,
};
void
*
buffer
=
NULL
;
log_debug
(
""
,
"posix_memalign"
);
/* Allocate user space memory for xdp frames */
ret
=
posix_memalign
(
&
buffer
,
sysconf
(
_SC_PAGE_SIZE
),
NUM_FRAMES
*
FRAME_SIZE
);
if
(
ret
)
err_errno
(
"posix_memalign() failed"
);
log_debug
(
""
,
"xsk_umem__create"
);
ret
=
xsk_umem__create
(
&
recv_xdp_socket
.
umem
.
umem
,
buffer
,
NUM_FRAMES
*
FRAME_SIZE
,
&
recv_xdp_socket
.
umem
.
fq
,
&
recv_xdp_socket
.
umem
.
cq
,
&
cfg
);
if
(
ret
)
err
(
"xsk_umem__create() failed"
);
recv_xdp_socket
.
umem
.
buffer
=
buffer
;
log_debug
(
""
,
"open_xdp_socket"
);
/* Create XDP socket */
xsk_cfg
.
rx_size
=
XSK_RING_CONS__DEFAULT_NUM_DESCS
;
xsk_cfg
.
tx_size
=
XSK_RING_PROD__DEFAULT_NUM_DESCS
;
xsk_cfg
.
libbpf_flags
=
0
;
xsk_cfg
.
xdp_flags
=
XDP_FLAGS_DRV_MODE
;
xsk_cfg
.
bind_flags
=
0
;
log_debug
(
""
,
"xsk_socket__create"
);
ret
=
xsk_socket__create
(
&
recv_xdp_socket
.
xsk
,
network_if
,
0
,
recv_xdp_socket
.
umem
.
umem
,
&
recv_xdp_socket
.
rx
,
&
recv_xdp_socket
.
tx
,
&
xsk_cfg
);
log_debug
(
""
,
"recv_xdp_packet"
);
recv_xdp_packet
();
}
static
void
send_xdp_packet
(
void
)
{
struct
pollfd
fds
[
1
]
=
{};
int
i
,
ret
;
fds
[
0
].
fd
=
xsk_socket__fd
(
send_xdp_socket
.
xsk
);
fds
[
0
].
events
=
POLLOUT
;
for
(
int
i
=
0
;
i
<
NUM_FRAMES
;
i
++
)
memcpy
(
xsk_umem__get_data
(
send_xdp_socket
.
umem
.
buffer
,
i
*
XSK_UMEM__DEFAULT_FRAME_SIZE
),
pkt_data
,
PACKET_SIZE
-
ETH_FCS_SIZE
);
while
(
1
)
{
int
batch_size
=
64
;
uint32_t
idx
;
log_debug
(
""
,
"polling"
);
ret
=
poll
(
fds
,
1
,
-
1
);
if
((
ret
<=
0
)
||
!
(
fds
[
0
].
revents
&
POLLOUT
))
continue
;
log_debug
(
""
,
"reserve"
);
xsk_ring_prod__reserve
(
&
send_xdp_socket
.
tx
,
batch_size
,
&
idx
);
for
(
int
k
=
0
;
k
<
batch_size
;
k
++
)
{
struct
xdp_desc
*
tx_desc
=
xsk_ring_prod__tx_desc
(
&
send_xdp_socket
.
tx
,
idx
+
k
);
tx_desc
->
addr
=
k
*
(
PACKET_SIZE
);
tx_desc
->
len
=
PACKET_SIZE
-
ETH_FCS_SIZE
;
}
log_debug
(
""
,
"submit"
);
xsk_ring_prod__submit
(
&
send_xdp_socket
.
tx
,
batch_size
);
log_debug
(
""
,
"submit done"
);
break
;
}
}
static
int
recv_xdp_packet
(
void
)
{
int
ret
;
static
struct
pollfd
fds_recv
[
1
]
=
{
0
};
fds_recv
[
0
].
fd
=
xsk_socket__fd
(
recv_xdp_socket
.
xsk
);
fds_recv
[
0
].
events
=
POLLIN
;
/* Add some buffers in fill ring */
log_debug
(
""
,
"xsk_ring_prod__reserve"
);
ret
=
xsk_ring_prod__reserve
(
&
recv_xdp_socket
.
umem
.
fq
,
XSK_RING_PROD__DEFAULT_NUM_DESCS
,
&
idx_recv
);
if
(
ret
!=
XSK_RING_PROD__DEFAULT_NUM_DESCS
)
err
(
"xsk_ring_prod__reserve() failed"
);
log_debug
(
""
,
"xsk_ring_prod__fill_addr"
);
for
(
int
i
=
0
;
i
<
XSK_RING_PROD__DEFAULT_NUM_DESCS
;
i
++
)
*
xsk_ring_prod__fill_addr
(
&
recv_xdp_socket
.
umem
.
fq
,
idx_recv
++
)
=
i
*
FRAME_SIZE
;
log_debug
(
""
,
"xsk_ring_prod__submit"
);
xsk_ring_prod__submit
(
&
recv_xdp_socket
.
umem
.
fq
,
XSK_RING_PROD__DEFAULT_NUM_DESCS
);
ret
=
poll
(
fds_recv
,
1
,
-
1
);
if
(
ret
!=
1
)
error
(
EXIT_FAILURE
,
errno
,
"poll failed"
);
log_info
(
""
,
"xsk_ring_cons__peek"
);
received
=
xsk_ring_cons__peek
(
&
recv_xdp_socket
.
rx
,
1
,
&
idx_rx
);
log_info
(
""
,
"Received packet ! (%d)"
,
received
);
if
(
received
!=
1
)
error
(
EXIT_FAILURE
,
errno
,
"Received %d packets"
,
received
);
return
0
;
}
static
void
recv_xdp_cleanup
(
void
)
{
uint64_t
addr
;
int
ret
;
/* Cleanup */
xsk_ring_cons__release
(
&
recv_xdp_socket
.
rx
,
received
);
/* Add that particular buffer back to the fill queue */
if
(
xsk_prod_nb_free
(
&
recv_xdp_socket
.
umem
.
fq
,
received
))
{
ret
=
xsk_ring_prod__reserve
(
&
recv_xdp_socket
.
umem
.
fq
,
received
,
&
idx_recv
);
if
(
ret
!=
received
)
err
(
"xsk_ring_prod__reserve() failed"
);
*
xsk_ring_prod__fill_addr
(
&
recv_xdp_socket
.
umem
.
fq
,
idx_recv
)
=
xsk_umem__extract_addr
(
addr
);
xsk_ring_prod__submit
(
&
recv_xdp_socket
.
umem
.
fq
,
received
);
}
}
static
void
close_xdp_socket
(
void
)
{
xsk_socket__delete
(
send_xdp_socket
.
xsk
);
xsk_socket__delete
(
recv_xdp_socket
.
xsk
);
xsk_umem__delete
(
send_xdp_socket
.
umem
.
umem
);
xsk_umem__delete
(
recv_xdp_socket
.
umem
.
umem
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment