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
4 years ago
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)
...
...
This diff is collapsed.
Click to expand it.
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
])
{
...
...
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
;
}
}
...
...
This diff is collapsed.
Click to expand it.
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
;
...
...
This diff is collapsed.
Click to expand it.
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