Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
tsn-measures
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
tsn-measures
Commits
e722e90d
Commit
e722e90d
authored
Jun 16, 2020
by
Joanne Hugé
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make the code compile with XDP on
parent
b1f3a35a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
190 additions
and
138 deletions
+190
-138
packet-exchange/build/Makefile
packet-exchange/build/Makefile
+6
-0
packet-exchange/src/recv_packet.c
packet-exchange/src/recv_packet.c
+100
-91
packet-exchange/src/recv_packet.h
packet-exchange/src/recv_packet.h
+22
-2
packet-exchange/src/server.c
packet-exchange/src/server.c
+44
-24
packet-exchange/src/utilities.h
packet-exchange/src/utilities.h
+18
-21
No files found.
packet-exchange/build/Makefile
View file @
e722e90d
...
...
@@ -27,6 +27,12 @@ CFLAGS += -std=gnu99
LDFLAGS
=
-pthread
ifeq
($(WITH_XDP),)
else
CFLAGS
+=
-D
WITH_XDP
LDFLAGS
+=
-L
/usr/lib
-lbpf
endif
vpath
%.c
$(SRCDIR)
$(SERVER_PROG)
:
$(SERVER_OBJS)
...
...
packet-exchange/src/recv_packet.c
View file @
e722e90d
...
...
@@ -3,8 +3,10 @@
#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>
...
...
@@ -12,6 +14,7 @@
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
...
...
@@ -23,13 +26,34 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "send_packet.h"
#include <net/if.h>
#include <netdb.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include "recv_packet.h"
#include "utilities.h"
#ifdef WITH_XDP
#include <linux/if_ether.h>
#include <linux/if_link.h>
#include <linux/if_xdp.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <bpf/xsk.h>
#endif
static
void
fill_histograms
(
packet_info_t
*
packet_info
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
]);
static
void
open_xdp_socket
(
void
);
static
char
rx_buffer
[
MAX_BUFFER_SIZE
];
static
int
sock_fd
;
...
...
@@ -168,23 +192,67 @@ packet_info_t recv_udp_packet(int use_timestamps, int use_histograms, int64_t hi
return
packet_info
;
}
#ifdef WITH_XDP
static
int
xdp_flags
=
XDP_FLAGS_DRV_MODE
;
static
struct
pollfd
fds
[
1
]
=
{
0
};
static
unsigned
int
ifindex
;
static
struct
xdpsock
xdp_socket
;
static
void
open_xdp_socket
(
char
*
network_if
)
{
struct
xsk_socket_config
xsk_cfg
;
uint32_t
idx
;
int
ret
,
i
;
/* 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
;
xsk_cfg
.
bind_flags
=
0
;
ret
=
xsk_socket__create
(
&
xdp_socket
.
xsk
,
network_if
,
0
,
xdp_socket
.
umem
.
umem
,
&
xdp_socket
.
rx
,
&
xdp_socket
.
tx
,
&
xsk_cfg
);
if
(
ret
)
err
(
"xsk_socket__create() failed"
);
/* Add some buffers */
ret
=
xsk_ring_prod__reserve
(
&
xdp_socket
.
umem
.
fq
,
XSK_RING_PROD__DEFAULT_NUM_DESCS
,
&
idx
);
if
(
ret
!=
XSK_RING_PROD__DEFAULT_NUM_DESCS
)
err
(
"xsk_ring_prod__reserve() failed"
);
for
(
i
=
0
;
i
<
XSK_RING_PROD__DEFAULT_NUM_DESCS
;
i
++
)
*
xsk_ring_prod__fill_addr
(
&
xdp_socket
.
umem
.
fq
,
idx
++
)
=
i
*
FRAME_SIZE
;
xsk_ring_prod__submit
(
&
xdp_socket
.
umem
.
fq
,
XSK_RING_PROD__DEFAULT_NUM_DESCS
);
fds
[
0
].
fd
=
xsk_socket__fd
(
xdp_socket
.
xsk
);
fds
[
0
].
events
=
POLLIN
;
}
#endif
/*
* Init XDP socket
*/
void
setup_xdp_socket
(
void
)
{
void
init_xdp_recv
(
char
*
network_if
)
{
#ifdef WITH_XDP
int
ret
,
prog_fd
,
xsks_map
=
0
;
struct
bpf_prog_load_attr
prog_load_attr
=
{
.
prog_type
=
BPF_PROG_TYPE_XDP
,
.
file
=
"xdp_kern.o"
,
.
file
=
"xdp_kern.o"
,
};
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
,
.
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
,
.
flags
=
0
,
};
struct
bpf_object
*
obj
;
struct
bpf_map
*
map
;
...
...
@@ -192,48 +260,48 @@ void setup_xdp_socket(void)
ret
=
bpf_prog_load_xattr
(
&
prog_load_attr
,
&
obj
,
&
prog_fd
);
if
(
ret
||
prog_fd
<
0
)
err
(
"bpf_prog_load_xattr() failed"
);
err
(
"bpf_prog_load_xattr() failed"
);
map
=
bpf_object__find_map_by_name
(
obj
,
"xsks_map"
);
xsks_map
=
bpf_map__fd
(
map
);
if
(
xsks_map
<
0
)
err
(
"No xsks_map found!"
);
err
(
"No xsks_map found!"
);
ifindex
=
if_nametoindex
(
interface
);
ifindex
=
if_nametoindex
(
network_if
);
if
(
!
ifindex
)
err_errno
(
"if_nametoindex() failed"
);
err_errno
(
"if_nametoindex() failed"
);
/* Use XDP _only_ in conjuction with driver assisted mode */
ret
=
bpf_set_link_xdp_fd
(
ifindex
,
prog_fd
,
xdp_flags
()
);
ret
=
bpf_set_link_xdp_fd
(
ifindex
,
prog_fd
,
xdp_flags
);
if
(
ret
)
err
(
"bpf_set_link_xdp_fd() failed"
);
err
(
"bpf_set_link_xdp_fd() failed"
);
/* 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"
);
err_errno
(
"posix_memalign() failed"
);
ret
=
xsk_umem__create
(
&
xdp_socket
.
umem
.
umem
,
buffer
,
NUM_FRAMES
*
FRAME_SIZE
,
&
xdp_socket
.
umem
.
fq
,
&
xdp_socket
.
umem
.
cq
,
&
cfg
);
if
(
ret
)
err
(
"xsk_umem__create() failed"
);
err
(
"xsk_umem__create() failed"
);
xdp_socket
.
umem
.
buffer
=
buffer
;
/* Open and bind socket */
open_xdp_socket
();
open_xdp_socket
(
network_if
);
#endif
}
/*
* Receive XDP socket
*/
void
recv_xdp_packet
(
void
)
{
int
recv_xdp_packet
(
struct
timespec
*
ts
)
{
#ifdef WITH_XDP
char
*
buffer
;
long
long
tx_time
,
diff
;
struct
timespec
ts
;
unsigned
int
received
;
uint64_t
addr
;
uint32_t
idx_rx
=
0
,
len
,
idx
;
...
...
@@ -241,9 +309,9 @@ void recv_xdp_packet(void) {
ret
=
poll
(
fds
,
1
,
-
1
);
if
(
ret
==
0
)
return
;
return
1
;
if
(
ret
<
0
)
error
(
EXIT_FAILURE
,
errno
,
"poll failed"
);
error
(
EXIT_FAILURE
,
errno
,
"poll failed"
);
/*
* Process packets: One at a time is enough for cyclic apps. Just
...
...
@@ -252,89 +320,30 @@ void recv_xdp_packet(void) {
*/
received
=
xsk_ring_cons__peek
(
&
xdp_socket
.
rx
,
1
,
&
idx_rx
);
if
(
!
received
)
return
;
return
1
;
/* Get current time */
ret
=
clock_gettime
(
CLOCK_TAI
,
&
ts
);
clock_gettime
(
CLOCK_MONOTONIC
,
ts
);
if
(
received
!=
1
)
error
(
EXIT_FAILURE
,
errno
,
"Received more packets than expected"
);
/* Get the packet */
addr
=
xsk_ring_cons__rx_desc
(
&
xdp_socket
.
rx
,
idx_rx
)
->
addr
;
len
=
xsk_ring_cons__rx_desc
(
&
xdp_socket
.
rx
,
idx_rx
)
->
len
;
/* Parse it */
buffer
=
parse_raw_packet
(
xsk_umem__add_offset_to_addr
(
addr
),
len
);
if
(
!
buffer
)
return
;
/* Decode */
ret
=
sscanf
(
buffer
,
"KURT: %lld"
,
&
tx_time
);
if
(
ret
!=
1
)
{
log_err
(
"Failed to decode package"
);
return
;
}
error
(
EXIT_FAILURE
,
errno
,
"Received more packets than expected"
);
/* Cleanup */
xsk_ring_cons__release
(
&
xdp_socket
.
rx
,
received
);
/* Add that particular buffer back to the fill queue */
if
(
xsk_prod_nb_free
(
&
xdp_socket
.
umem
.
fq
,
received
))
{
ret
=
xsk_ring_prod__reserve
(
&
xdp_socket
.
umem
.
fq
,
received
,
&
idx
);
ret
=
xsk_ring_prod__reserve
(
&
xdp_socket
.
umem
.
fq
,
received
,
&
idx
);
if
(
ret
!=
received
)
err
(
"xsk_ring_prod__reserve() failed"
);
if
(
ret
!=
received
)
err
(
"xsk_ring_prod__reserve() failed"
);
*
xsk_ring_prod__fill_addr
(
&
xdp_socket
.
umem
.
fq
,
idx
)
=
xsk_umem__extract_addr
(
addr
);
xsk_ring_prod__submit
(
&
xdp_socket
.
umem
.
fq
,
received
);
}
*
xsk_ring_prod__fill_addr
(
&
xdp_socket
.
umem
.
fq
,
idx
)
=
xsk_umem__extract_addr
(
addr
);
/* Update stats */
diff
=
update_stats
(
&
ts
,
tx_time
);
if
(
break_value_ns
&&
diff
>
break_value_ns
)
{
stop_tracing
();
stop
=
1
;
break
;
xsk_ring_prod__submit
(
&
xdp_socket
.
umem
.
fq
,
received
);
}
#endif
}
static
void
open_xdp_socket
(
void
)
{
struct
xsk_socket_config
xsk_cfg
;
uint32_t
idx
;
int
ret
,
i
;
/* 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
();
xsk_cfg
.
bind_flags
=
0
;
ret
=
xsk_socket__create
(
&
xdp_socket
.
xsk
,
interface
,
queue
,
xdp_socket
.
umem
.
umem
,
&
xdp_socket
.
rx
,
&
xdp_socket
.
tx
,
&
xsk_cfg
);
if
(
ret
)
err
(
"xsk_socket__create() failed"
);
/* Add some buffers */
ret
=
xsk_ring_prod__reserve
(
&
xdp_socket
.
umem
.
fq
,
XSK_RING_PROD__DEFAULT_NUM_DESCS
,
&
idx
);
if
(
ret
!=
XSK_RING_PROD__DEFAULT_NUM_DESCS
)
err
(
"xsk_ring_prod__reserve() failed"
);
for
(
i
=
0
;
i
<
XSK_RING_PROD__DEFAULT_NUM_DESCS
;
i
++
)
*
xsk_ring_prod__fill_addr
(
&
xdp_socket
.
umem
.
fq
,
idx
++
)
=
i
*
FRAME_SIZE
;
xsk_ring_prod__submit
(
&
xdp_socket
.
umem
.
fq
,
XSK_RING_PROD__DEFAULT_NUM_DESCS
);
return
0
;
}
static
void
fill_histograms
(
packet_info_t
*
packet_info
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
])
{
...
...
packet-exchange/src/recv_packet.h
View file @
e722e90d
...
...
@@ -3,10 +3,30 @@
#include "utilities.h"
#ifdef WITH_XDP
#define NUM_FRAMES 4096
#define FRAME_SIZE XSK_UMEM__DEFAULT_FRAME_SIZE
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
;
};
#endif
int
init_udp_recv
(
int
use_timestamps
,
char
*
network_if
);
packet_info_t
recv_udp_packet
(
int
use_timestamps
,
int
use_histograms
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
]);
void
setup_xdp_socket
(
void
);
void
recv_xdp_packet
(
void
);
void
init_xdp_recv
(
char
*
network_if
);
int
recv_xdp_packet
(
struct
timespec
*
ts
);
#endif
packet-exchange/src/server.c
View file @
e722e90d
...
...
@@ -28,18 +28,6 @@
#include "send_packet.h"
#include "utilities.h"
#ifdef WITH_XDP
#include <linux/if_link.h>
#include <linux/if_xdp.h>
#include <linux/if_ether.h>
#include <linux/udp.h>
#include <linux/ip.h>
#include <bpf/bpf.h>
#include <bpf/xsk.h>
#include <bpf/libbpf.h>
#endif
// Structs
typedef
struct
thread_stat
{
...
...
@@ -74,8 +62,6 @@ static void process_options(int argc, char *argv[]);
static
void
print_histograms
();
static
void
sighand
(
int
sig_num
);
static
void
setup_xdp_socket
(
void
);
// Static variables
static
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
];
...
...
@@ -89,7 +75,8 @@ static int enable_affinity;
static
int
enable_timestamps
;
enum
TSNTask
{
RECV_PACKET_TASK
,
RTT_TASK
};
RTT_TASK
,
XDP_TASK
};
static
enum
TSNTask
tsn_task
;
struct
timespec
measures_start
;
...
...
@@ -181,6 +168,29 @@ static void *packet_receiving_thread(void *p) {
previous
=
current
;
prev_packet_id
=
current_packet_id
;
}
else
if
(
tsn_task
==
XDP_TASK
)
{
if
(
recv_xdp_packet
(
&
current
))
continue
;
if
(
stats
->
packets_received
)
{
diff
=
calcdiff_ns
(
current
,
previous
);
stats
->
min_interval
=
diff
<
stats
->
min_interval
?
diff
:
stats
->
min_interval
;
stats
->
max_interval
=
diff
>
stats
->
max_interval
?
diff
:
stats
->
max_interval
;
if
(
enable_histograms
)
{
dist_to_interval
=
(((
int64_t
)
diff
)
-
param
->
interval
)
/
1000
;
dist_to_interval
+=
MAX_HIST_VAL
/
2
;
if
(
dist_to_interval
>
((
int
)
MAX_HIST_VAL
)
||
dist_to_interval
<
0
)
fprintf
(
stderr
,
"jitter higher than MAX_HIST_VAL: %"
PRIi64
"
\n
"
,
dist_to_interval
);
else
histograms
[
2
][
dist_to_interval
]
++
;
}
}
previous
=
current
;
}
}
...
...
@@ -221,12 +231,20 @@ int main(int argc, char *argv[]) {
// Catch breaks with sighand to print the histograms
init_signals
(
sighand
,
enable_histograms
);
// Initialize the UDP packet receiving socket
init_udp_recv
(
enable_timestamps
,
network_config
.
network_if
);
if
(
tsn_task
==
XDP_TASK
)
{
// Initialize the XDP packet receiving socket
init_xdp_recv
(
network_config
.
network_if
);
// Initialize the UDP packet sending socket if RTT is measured
if
(
tsn_task
==
RTT_TASK
)
init_udp_send
(
0
,
0
,
1
,
network_config
.
network_if
,
network_config
.
tx_buffer_len
);
}
else
{
// Initialize the UDP packet receiving socket
init_udp_recv
(
enable_timestamps
,
network_config
.
network_if
);
// Initialize the UDP packet sending socket if RTT is measured
if
(
tsn_task
==
RTT_TASK
)
init_udp_send
(
0
,
0
,
1
,
network_config
.
network_if
,
network_config
.
tx_buffer_len
);
}
// Create the real time thread
if
(
pthread_create
(
&
thread
,
NULL
,
packet_receiving_thread
,
(
void
*
)
param
))
...
...
@@ -256,12 +274,11 @@ int main(int argc, char *argv[]) {
10
,
kernel_space_time
,
4
,
stats
->
packet_info
.
data
,
4
,
stats
->
lost_packets
);
}
else
{
}
else
{
printf
(
"
\n
"
);
}
printf
(
"
\033
[%dA"
,
1
);
printf
(
"
\033
[%dA"
,
1
);
}
}
}
...
...
@@ -359,7 +376,7 @@ static void process_options(int argc, char *argv[]) {
int
network_if_specified
=
0
;
for
(;;)
{
int
c
=
getopt
(
argc
,
argv
,
"ab:d:f:ghi:p:r:tv"
);
int
c
=
getopt
(
argc
,
argv
,
"ab:d:f:ghi:p:r:tv
x
"
);
if
(
c
==
-
1
)
break
;
...
...
@@ -405,6 +422,9 @@ static void process_options(int argc, char *argv[]) {
case
'v'
:
main_param
.
verbose
=
1
;
break
;
case
'x'
:
tsn_task
=
XDP_TASK
;
break
;
}
}
...
...
packet-exchange/src/utilities.h
View file @
e722e90d
...
...
@@ -8,6 +8,18 @@
#include <time.h>
#include <unistd.h>
#ifdef WITH_XDP
#include <linux/if_ether.h>
#include <linux/if_link.h>
#include <linux/if_xdp.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <bpf/xsk.h>
#endif
#define NSEC_PER_SEC UINT64_C(1000000000)
#define SERVER_PORT "50000"
#define SERVER_PORT_INT 50000
...
...
@@ -15,28 +27,13 @@
#define NB_HISTOGRAMS 3
#define MAX_BUFFER_SIZE 1024
// XDP
#ifdef WITH_XDP
#define NUM_FRAMES 4096
#define FRAME_SIZE XSK_UMEM__DEFAULT_FRAME_SIZE
unsigned
int
ifindex
;
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
struct
xdpsock
xdp_socket
;
#endif
#define err(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
exit(EXIT_FAILURE); \
} while (0)
#define err_errno(...) error(EXIT_FAILURE, errno, __VA_ARGS__);
typedef
struct
packet_info
{
uint64_t
userspace_enter_ts
;
...
...
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