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
33d0cb10
Commit
33d0cb10
authored
Jun 04, 2020
by
Joanne Hugé
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'packet-exchange' into measure-analysis
parents
7eeb79bf
612189aa
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
540 additions
and
224 deletions
+540
-224
packet-exchange/src/client.c
packet-exchange/src/client.c
+52
-50
packet-exchange/src/recv_packet.c
packet-exchange/src/recv_packet.c
+173
-19
packet-exchange/src/recv_packet.h
packet-exchange/src/recv_packet.h
+4
-2
packet-exchange/src/send_packet.c
packet-exchange/src/send_packet.c
+46
-39
packet-exchange/src/send_packet.h
packet-exchange/src/send_packet.h
+2
-11
packet-exchange/src/server.c
packet-exchange/src/server.c
+255
-100
packet-exchange/src/utilities.c
packet-exchange/src/utilities.c
+0
-1
packet-exchange/src/utilities.h
packet-exchange/src/utilities.h
+8
-2
No files found.
packet-exchange/src/client.c
View file @
33d0cb10
/*
* Real time packet sending
thread
* Real time packet sending
client
*
* Large portions taken from cyclictest
*
...
...
@@ -27,7 +27,7 @@
typedef
struct
thread_stat
{
int
nb_cycles
;
uint64_t
rtt
;
struct
packet_timestamps
packet_ts
;
packet_timestamps_t
packet_ts
;
}
thread_stat_t
;
typedef
struct
thread_param
{
...
...
@@ -74,6 +74,9 @@ enum TSNTask { SEND_PACKET_TASK,
RTT_TASK
};
static
enum
TSNTask
tsn_task
;
struct
timespec
measures_start
;
struct
timespec
measures_end
;
static
void
help
(
char
*
argv
[])
{
printf
(
"Usage: %s -f IF [-abethgv] [-d BUF_LEN] [-i USEC] [-l N] [-p PRIO] [-r USEC]
\n\n
"
,
argv
[
0
]);
printf
(
" -a Run the real time thread on CPU1
\n
"
);
...
...
@@ -99,7 +102,7 @@ static void *packet_sending_thread(void *p) {
uint64_t
next_txtime
;
struct
sched_param
priority
;
thread_param_t
*
param
=
(
thread_param_t
*
)
p
;
thread_stat_t
*
stats
=
&
param
->
stats
;
thread_stat_t
*
stats
=
&
param
->
stats
;
cpu_set_t
mask
;
// Set thread CPU affinity
...
...
@@ -122,6 +125,7 @@ static void *packet_sending_thread(void *p) {
// Send packet while thread is sleeping
next_txtime
+=
(
param
->
interval
)
/
2
;
clock_gettime
(
CLOCK_MONOTONIC
,
&
measures_start
);
// Packet sending loop
for
(
stats
->
nb_cycles
=
0
;;
stats
->
nb_cycles
++
)
{
if
(
param
->
max_cycles
)
...
...
@@ -184,7 +188,7 @@ int main(int argc, char *argv[]) {
// Initialize the UDP packet receiving socket if RTT is measured
if
(
tsn_task
==
RTT_TASK
)
init_udp_recv
();
init_udp_recv
(
0
,
network_config
.
network_if
);
// Create the real time thread
if
(
pthread_create
(
&
thread
,
NULL
,
packet_sending_thread
,
(
void
*
)
param
))
...
...
@@ -201,13 +205,15 @@ int main(int argc, char *argv[]) {
}
else
if
(
enable_timestamps
)
{
printf
(
"(%d)
\n
"
,
stats
->
nb_cycles
);
printf
(
" Enter send_udp_packet timestamp: %"
PRIu64
"
\n
"
,
stats
->
packet_ts
.
user_enter_send
);
printf
(
" Call sendmsg timestamp : %"
PRIu64
"
\n
"
,
stats
->
packet_ts
.
user_call_sendmsg
);
printf
(
" Leave kernel timestamp : %"
PRIu64
"
\n
"
,
stats
->
packet_ts
.
kernel_leave
);
printf
(
"(%d) Enter send_udp_packet timestamp: %"
PRIu64
"
\n
"
,
stats
->
nb_cycles
,
stats
->
packet_ts
.
enter_user_space
);
printf
(
"(%d) Call sendmsg timestamp : %"
PRIu64
"
\n
"
,
stats
->
nb_cycles
,
stats
->
packet_ts
.
enter_kernel
);
printf
(
"(%d) Leave kernel timestamp : %"
PRIu64
"
\n
"
,
stats
->
nb_cycles
,
stats
->
packet_ts
.
leave_kernel
);
}
}
...
...
@@ -233,60 +239,57 @@ static void do_tsn_task(struct thread_param *param, uint64_t next_txtime) {
enable_etf
,
enable_timestamps
,
next_txtime
,
network_config
.
ip_address
,
histograms
);
// Round Trip Time measurement
// Round Trip Time measurement
}
else
if
(
tsn_task
==
RTT_TASK
)
{
clock_gettime
(
CLOCK_MONOTONIC
,
&
t1
);
send_udp_packet
(
enable_etf
,
enable_timestamps
,
next_txtime
,
network_config
.
ip_address
,
histograms
);
recv_udp_packet
();
send_udp_packet
(
0
,
0
,
next_txtime
,
network_config
.
ip_address
,
NULL
);
recv_udp_packet
(
0
,
NULL
);
clock_gettime
(
CLOCK_MONOTONIC
,
&
t2
);
param
->
stats
.
rtt
=
calcdiff_ns
(
t2
,
t1
);
}
}
// Print histograms in .json format
static
void
print_histograms
()
{
printf
(
"{
\"
measure_type
\"
:
\"
packet_timestamps
\"
,\
\"
props_names
\"
: [
\"
user_space
\"
,
\"
kernel_space
\"
],\
\"
units
\"
: [
\"
us
\"
,
\"
us
\"
],\
\"
props
\"
: ["
);
uint64_t
duration
;
int
duration_hour
,
duration_minutes
,
interval
;
clock_gettime
(
CLOCK_MONOTONIC
,
&
measures_end
);
duration
=
calcdiff_ns
(
measures_end
,
measures_start
);
duration_hour
=
duration
/
NSEC_PER_SEC
/
3600
;
duration_minutes
=
duration
/
NSEC_PER_SEC
/
60
-
duration_hour
*
60
;
interval
=
param
->
interval
/
1000
;
printf
(
"{
\"
measure_sets
\"
: [{"
"
\"
measure_type
\"
:
\"
packet_send_timestamps
\"
,"
"
\"
props_names
\"
: [
\"
user_space
\"
,
\"
kernel_space
\"
],"
"
\"
units
\"
: [
\"
us
\"
,
\"
us
\"
],"
"
\"
props_type
\"
:
\"
histogram
\"
,"
"
\"
metadata
\"
: {"
"
\"
i
\"
:
\"
%dus
\"
,
\"
duration
\"
:
\"
%dh%d
\"
"
"},"
"
\"
props
\"
: ["
,
interval
,
duration_hour
,
duration_minutes
);
int
max_hist_val
=
0
;
for
(
int
i
=
0
;
i
<
NB_HISTOGRAMS
;
i
++
)
{
for
(
int
i
=
0
;
i
<
2
;
i
++
)
for
(
int
j
=
0
;
j
<
MAX_HIST_VAL
;
j
++
)
if
(
histograms
[
i
][
j
])
max_hist_val
=
j
>
max_hist_val
?
j
:
max_hist_val
;
}
for
(
int
i
=
0
;
i
<
NB_HISTOGRAMS
;
i
++
)
{
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
printf
(
"["
);
for
(
int
j
=
0
;
j
<
max_hist_val
;
j
++
)
{
if
(
j
+
1
<
max_hist_val
)
printf
(
"%"
PRIi64
", "
,
histograms
[
i
][
j
]);
else
printf
(
"%"
PRIi64
,
histograms
[
i
][
j
]);
}
if
(
i
+
1
<
NB_HISTOGRAMS
)
printf
(
"], "
);
else
printf
(
"]"
);
for
(
int
j
=
0
;
j
<
max_hist_val
;
j
++
)
printf
(
"%"
PRIi64
"%s"
,
histograms
[
i
][
j
],
(
j
+
1
<
max_hist_val
?
", "
:
""
));
printf
(
"%s"
,
(
i
+
1
<
2
?
"], "
:
"]"
));
}
int
interval
=
param
->
interval
/
1000
;
uint64_t
duration
=
interval
*
param
->
stats
.
nb_cycles
;
int
duration_hour
=
duration
/
1000000
;
duration_hour
/=
3600
;
int
duration_minutes
=
duration
/
1000000
;
duration_minutes
/=
60
;
duration_minutes
-=
duration_hour
*
60
;
printf
(
"], "
);
printf
(
"
\"
props_type
\"
:
\"
histogram
\"
,
\"
metadata
\"
: {
\"
i
\"
:
\"
%dus
\"
,
\"
duration
\"
:
\"
%dh%d
\"
}}
\n
"
,
interval
,
duration_hour
,
duration_minutes
);
printf
(
"]]}]}
\n
"
);
}
static
void
sigint_handler
(
int
sig_num
)
{
...
...
@@ -359,14 +362,14 @@ static void process_options(int argc, char *argv[]) {
}
}
if
(
!
network_if_specified
)
{
fprintf
(
stderr
,
"You need to specifiy an network interface
\n
"
);
help
(
argv
);
exit
(
EXIT_FAILURE
);
if
(
!
network_if_specified
)
{
fprintf
(
stderr
,
"You need to specifiy an network interface
\n
"
);
help
(
argv
);
exit
(
EXIT_FAILURE
);
}
if
(
argc
!=
optind
+
1
)
{
if
(
argc
<
optind
+
1
)
if
(
argc
<
optind
+
1
)
fprintf
(
stderr
,
"You need to specifiy an IP address
\n
"
);
else
fprintf
(
stderr
,
"Too many arguments
\n
"
);
...
...
@@ -375,4 +378,3 @@ static void process_options(int argc, char *argv[]) {
}
strcpy
(
network_config
.
ip_address
,
argv
[
optind
]);
}
packet-exchange/src/recv_packet.c
View file @
33d0cb10
...
...
@@ -2,31 +2,60 @@
#include <arpa/inet.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <inttypes.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/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "send_packet.h"
#include "utilities.h"
#define SERVER_PORT "50000"
#define BUFFER_SIZE 1024
static
void
fill_histograms
(
packet_timestamps_t
*
packet_ts
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
]);
static
char
rx_buffer
[
BUFFER_SIZE
];
static
int
sock_fd
;
int
init_udp_recv
()
{
int
status
;
int
sock_fd
=
-
1
;
static
int
so_timestamping_flags
=
SOF_TIMESTAMPING_RX_SOFTWARE
|
SOF_TIMESTAMPING_SOFTWARE
;
// Sets the interface
static
int
set_if
(
char
*
network_if
)
{
struct
ifreq
ifreq
;
memset
(
&
ifreq
,
0
,
sizeof
(
ifreq
));
strncpy
(
ifreq
.
ifr_name
,
network_if
,
sizeof
(
ifreq
.
ifr_name
)
-
1
);
if
(
ioctl
(
sock_fd
,
SIOCGIFINDEX
,
&
ifreq
))
error
(
EXIT_FAILURE
,
errno
,
"ioctl SIOCGIFINDEX failed
\n
"
);
return
ifreq
.
ifr_ifindex
;
}
int
init_udp_recv
(
int
use_timestamps
,
char
*
network_if
)
{
int
getaddrinfo_err
;
int
set_if_err
;
struct
addrinfo
hints
,
*
servinfo
,
*
servinfo_it
;
memset
(
&
hints
,
0
,
sizeof
hints
);
...
...
@@ -34,16 +63,16 @@ int init_udp_recv() {
hints
.
ai_socktype
=
SOCK_DGRAM
;
hints
.
ai_flags
=
AI_PASSIVE
;
status
=
getaddrinfo
(
NULL
,
SERVER_PORT
,
&
hints
,
&
servinfo
);
if
(
status
!=
0
)
{
fprintf
(
stderr
,
"getaddrinfo: %s
\n
"
,
gai_strerror
(
status
));
getaddrinfo_err
=
getaddrinfo
(
NULL
,
SERVER_PORT
,
&
hints
,
&
servinfo
);
if
(
getaddrinfo_err
!=
0
)
{
fprintf
(
stderr
,
"getaddrinfo: %s
\n
"
,
gai_strerror
(
getaddrinfo_err
));
exit
(
EXIT_FAILURE
);
}
for
(
servinfo_it
=
servinfo
;
servinfo_it
;
servinfo_it
=
servinfo_it
->
ai_next
)
{
sock_fd
=
socket
(
servinfo
->
ai_family
,
servinfo
->
ai_socktype
,
servinfo
->
ai_protocol
);
servinfo
->
ai_protocol
);
if
(
bind
(
sock_fd
,
servinfo_it
->
ai_addr
,
servinfo_it
->
ai_addrlen
)
==
-
1
)
{
close
(
sock_fd
);
...
...
@@ -54,23 +83,148 @@ int init_udp_recv() {
freeaddrinfo
(
servinfo
);
if
(
sock_fd
==
-
1
)
if
(
sock_fd
==
-
1
)
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create receive socket"
);
printf
(
"waiting to receive...
\n
"
);
set_if_err
=
set_if
(
network_if
);
if
(
set_if_err
<
0
)
error
(
EXIT_FAILURE
,
errno
,
"Couldn't set interface
\n
"
);
if
(
setsockopt
(
sock_fd
,
SOL_SOCKET
,
SO_BINDTODEVICE
,
network_if
,
strlen
(
network_if
)))
error
(
EXIT_FAILURE
,
errno
,
"setsockopt SO_BINDTODEVICE failed
\n
"
);
if
(
use_timestamps
)
{
if
(
setsockopt
(
sock_fd
,
SOL_SOCKET
,
SO_TIMESTAMPING
,
&
so_timestamping_flags
,
sizeof
(
so_timestamping_flags
)))
error
(
EXIT_FAILURE
,
errno
,
"setsockopt SO_TIMESTAMPING failed
\n
"
);
}
return
sock_fd
;
}
void
recv_udp_packet
()
{
/*
* Receives udp packets
*/
packet_timestamps_t
recv_udp_packet
(
int
use_timestamps
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
])
{
struct
cmsghdr
*
cmsg
;
struct
msghdr
msg
;
// Message hardware, sent to the socket
struct
iovec
iov
;
// The iovec structures stores the RX buffer
struct
sockaddr_in
sin
;
int
recvmsgerr
;
packet_timestamps_t
packet_ts
;
struct
timespec
ts
;
if
(
use_timestamps
)
{
clock_gettime
(
CLOCK_REALTIME
,
&
ts
);
packet_ts
.
enter_user_space
=
ts_to_uint
(
ts
);
}
iov
.
iov_base
=
&
rx_buffer
;
iov
.
iov_len
=
BUFFER_SIZE
-
1
;
memset
(
&
msg
,
0
,
sizeof
(
msg
));
msg
.
msg_name
=
&
sin
;
msg
.
msg_namelen
=
sizeof
(
sin
);
msg
.
msg_iov
=
&
iov
;
msg
.
msg_iovlen
=
1
;
if
(
use_timestamps
)
{
clock_gettime
(
CLOCK_REALTIME
,
&
ts
);
packet_ts
.
enter_kernel
=
ts_to_uint
(
ts
);
}
recvmsgerr
=
recvmsg
(
sock_fd
,
&
msg
,
0
);
if
(
recvmsgerr
<
0
)
error
(
EXIT_FAILURE
,
errno
,
"recvmsg failed, ret value: %d
\n
"
,
recvmsgerr
);
if
(
use_timestamps
)
{
for
(
cmsg
=
CMSG_FIRSTHDR
(
&
msg
);
cmsg
;
cmsg
=
CMSG_NXTHDR
(
&
msg
,
cmsg
))
{
if
(
cmsg
->
cmsg_level
==
SOL_SOCKET
&&
cmsg
->
cmsg_type
==
SO_TIMESTAMPING
)
{
struct
timespec
*
stamp
=
(
struct
timespec
*
)
CMSG_DATA
(
cmsg
);
packet_ts
.
leave_kernel
=
ts_to_uint
(
*
stamp
);
fill_histograms
(
&
packet_ts
,
histograms
);
}
}
}
return
packet_ts
;
}
static
void
fill_histograms
(
packet_timestamps_t
*
packet_ts
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
])
{
uint64_t
user_space_time
=
packet_ts
->
enter_kernel
-
packet_ts
->
enter_user_space
;
uint64_t
kernel_space_time
=
packet_ts
->
leave_kernel
-
packet_ts
->
enter_kernel
;
user_space_time
/=
1000u
;
kernel_space_time
/=
1000u
;
if
(
user_space_time
>
MAX_HIST_VAL
)
{
fprintf
(
stderr
,
"user_space_time value too high: %"
PRIu64
"us
\n
"
,
user_space_time
);
exit
(
EXIT_FAILURE
);
}
if
(
kernel_space_time
>
MAX_HIST_VAL
)
{
fprintf
(
stderr
,
"kernel_space_time value too high: %"
PRIu64
"us
\n
"
,
kernel_space_time
);
exit
(
EXIT_FAILURE
);
}
histograms
[
0
][
user_space_time
]
++
;
histograms
[
1
][
kernel_space_time
]
++
;
}
#ifdef DEBUG
int
bytes_received
=
0
;
bytes_received
=
recvfrom
(
sock_fd
,
rx_buffer
,
BUFFER_SIZE
-
1
,
0
,
NULL
,
NULL
);
/*
* Code from scheduled_tx_tools
*/
static
int
process_socket_error_queue
()
{
uint8_t
msg_control
[
CMSG_SPACE
(
sizeof
(
struct
sock_extended_err
))];
unsigned
char
err_buffer
[
256
];
struct
sock_extended_err
*
serr
;
struct
cmsghdr
*
cmsg
;
__u64
tstamp
=
0
;
if
(
bytes_received
==
-
1
)
error
(
EXIT_FAILURE
,
errno
,
"Error while attempting to receive packets"
);
#else
recvfrom
(
sock_fd
,
rx_buffer
,
BUFFER_SIZE
-
1
,
0
,
NULL
,
NULL
);
#endif
struct
iovec
iov
=
{.
iov_base
=
err_buffer
,
.
iov_len
=
sizeof
(
err_buffer
)};
struct
msghdr
msg
=
{.
msg_iov
=
&
iov
,
.
msg_iovlen
=
1
,
.
msg_control
=
msg_control
,
.
msg_controllen
=
sizeof
(
msg_control
)};
if
(
recvmsg
(
sock_fd
,
&
msg
,
MSG_ERRQUEUE
)
==
-
1
)
{
fprintf
(
stderr
,
"recvmsg failed"
);
return
-
1
;
}
cmsg
=
CMSG_FIRSTHDR
(
&
msg
);
while
(
cmsg
!=
NULL
)
{
serr
=
(
void
*
)
CMSG_DATA
(
cmsg
);
if
(
serr
->
ee_origin
==
SO_EE_ORIGIN_TXTIME
)
{
tstamp
=
((
__u64
)
serr
->
ee_data
<<
32
)
+
serr
->
ee_info
;
switch
(
serr
->
ee_code
)
{
case
SO_EE_CODE_TXTIME_INVALID_PARAM
:
fprintf
(
stderr
,
"packet with tstamp %llu dropped due to invalid params
\n
"
,
tstamp
);
return
0
;
case
SO_EE_CODE_TXTIME_MISSED
:
fprintf
(
stderr
,
"packet with tstamp %llu dropped due to missed deadline
\n
"
,
tstamp
);
return
0
;
default:
return
-
1
;
}
}
cmsg
=
CMSG_NXTHDR
(
&
msg
,
cmsg
);
}
return
0
;
}
#endif
packet-exchange/src/recv_packet.h
View file @
33d0cb10
#ifndef RECV_PACKET
#define RECV_PACKET
int
init_udp_recv
();
void
recv_udp_packet
();
#include "utilities.h"
int
init_udp_recv
(
int
use_timestamps
,
char
*
network_if
);
packet_timestamps_t
recv_udp_packet
(
int
use_timestamps
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
]);
#endif
packet-exchange/src/send_packet.c
View file @
33d0cb10
...
...
@@ -7,7 +7,6 @@
*
*/
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <errno.h>
...
...
@@ -36,12 +35,12 @@
#include <sys/types.h>
#include <unistd.h>
#include "utilities.h"
#include "send_packet.h"
#include "utilities.h"
#define MESSAGE ((uint32_t)0x00FACADE)
static
void
process_timestamps
(
struct
packet_timestamps
*
packet_ts
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
]);
static
void
process_timestamps
(
packet_timestamps_t
*
packet_ts
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
]);
static
void
init_tx_buffer
(
size_t
_tx_buffer_len
);
static
int
so_priority
=
3
;
...
...
@@ -89,7 +88,7 @@ static void init_tx_buffer(size_t _tx_buffer_len) {
*/
void
init_udp_send
(
int
use_etf
,
int
use_timestamps
,
int
packet_priority
,
char
*
network_if
,
size_t
_tx_buffer_len
)
{
int
index
;
int
set_if_err
;
struct
timespec
ts_mon
;
struct
timespec
ts_tai
;
...
...
@@ -104,10 +103,12 @@ void init_udp_send(int use_etf, int use_timestamps, int packet_priority,
so_priority
=
packet_priority
;
sock_fd
=
socket
(
PF_INET
,
SOCK_DGRAM
,
IPPROTO_UDP
);
if
(
sock_fd
<
0
)
error
(
EXIT_FAILURE
,
errno
,
"Socket creation failed
\n
"
);
if
(
sock_fd
<
0
)
error
(
EXIT_FAILURE
,
errno
,
"Socket creation failed
\n
"
);
index
=
set_if
(
network_if
);
if
(
index
<
0
)
error
(
EXIT_FAILURE
,
errno
,
"Couldn't set interface
\n
"
);
set_if_err
=
set_if
(
network_if
);
if
(
set_if_err
<
0
)
error
(
EXIT_FAILURE
,
errno
,
"Couldn't set interface
\n
"
);
if
(
setsockopt
(
sock_fd
,
SOL_SOCKET
,
SO_PRIORITY
,
&
so_priority
,
sizeof
(
so_priority
)))
...
...
@@ -146,25 +147,26 @@ uint64_t get_txtime() {
/*
* Sends udp packets
*/
struct
packet_timestamps
send_udp_packet
(
int
use_etf
,
int
use_timestamps
,
packet_timestamps_t
send_udp_packet
(
int
use_etf
,
int
use_timestamps
,
uint64_t
txtime
,
const
char
*
server_ip
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
])
{
char
control
[
CMSG_SPACE
(
sizeof
(
txtime
))]
=
{};
struct
sockaddr_in
sin
;
struct
cmsghdr
*
cmsg
;
struct
msghdr
msg
;
struct
iovec
iov
;
int
sendmsgerr
;
int
res
;
struct
msghdr
msg
;
// Message hardware, sent to the socket
struct
cmsghdr
*
cmsg
;
// Control message hardware, for txtime
char
control
[
CMSG_SPACE
(
sizeof
(
txtime
))]
=
{};
// Stores txtime
struct
iovec
iov
;
// The iovec structures stores the TX buffer
// Poll file descriptor, used to poll for timestamp messages
struct
pollfd
poll_fd
=
{
sock_fd
,
POLLPRI
,
0
};
int
sendmsgerr
,
pollerr
;
// Server address
struct
sockaddr_in
sin
;
struct
packet_timestamps
packet_ts
;
packet_timestamps_t
packet_ts
;
struct
timespec
ts
;
if
(
use_timestamps
)
{
clock_gettime
(
CLOCK_REALTIME
,
&
ts
);
packet_ts
.
user_enter_send
=
ts_to_uint
(
ts
);
packet_ts
.
enter_user_space
=
ts_to_uint
(
ts
);
}
memset
(
&
sin
,
0
,
sizeof
(
sin
));
...
...
@@ -196,7 +198,7 @@ struct packet_timestamps send_udp_packet(int use_etf, int use_timestamps,
if
(
use_timestamps
)
{
clock_gettime
(
CLOCK_REALTIME
,
&
ts
);
packet_ts
.
user_call_sendmsg
=
ts_to_uint
(
ts
);
packet_ts
.
enter_kernel
=
ts_to_uint
(
ts
);
}
sendmsgerr
=
sendmsg
(
sock_fd
,
&
msg
,
0
);
...
...
@@ -204,8 +206,8 @@ struct packet_timestamps send_udp_packet(int use_etf, int use_timestamps,
error
(
EXIT_FAILURE
,
errno
,
"sendmsg failed, ret value: %d
\n
"
,
sendmsgerr
);
if
(
use_timestamps
)
{
res
=
poll
(
&
poll_fd
,
1
,
0
);
if
(
res
>
0
)
pollerr
=
poll
(
&
poll_fd
,
1
,
0
);
if
(
pollerr
>
0
)
process_timestamps
(
&
packet_ts
,
histograms
);
else
fprintf
(
stderr
,
"select failed
\n
"
);
...
...
@@ -214,18 +216,19 @@ struct packet_timestamps send_udp_packet(int use_etf, int use_timestamps,
return
packet_ts
;
}
static
void
fill_histograms
(
struct
packet_timestamps
*
packet_ts
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
])
{
uint64_t
user_space_time
=
packet_ts
->
user_call_sendmsg
-
packet_ts
->
user_enter_send
;
uint64_t
kernel_space_time
=
packet_ts
->
kernel_leave
-
packet_ts
->
user_call_sendmsg
;
static
void
fill_histograms
(
packet_timestamps_t
*
packet_ts
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
])
{
uint64_t
user_space_time
=
packet_ts
->
enter_kernel
-
packet_ts
->
enter_user_space
;
uint64_t
kernel_space_time
=
packet_ts
->
leave_kernel
-
packet_ts
->
enter_kernel
;
user_space_time
/=
1000u
;
kernel_space_time
/=
1000u
;
if
(
user_space_time
>
MAX_HIST_VAL
)
{
if
(
user_space_time
>
MAX_HIST_VAL
)
{
fprintf
(
stderr
,
"user_space_time value too high: %"
PRIu64
"us
\n
"
,
user_space_time
);
exit
(
EXIT_FAILURE
);
}
if
(
kernel_space_time
>
MAX_HIST_VAL
)
{
if
(
kernel_space_time
>
MAX_HIST_VAL
)
{
fprintf
(
stderr
,
"kernel_space_time value too high: %"
PRIu64
"us
\n
"
,
kernel_space_time
);
exit
(
EXIT_FAILURE
);
}
...
...
@@ -234,7 +237,7 @@ static void fill_histograms(struct packet_timestamps *packet_ts, int64_t histogr
histograms
[
1
][
kernel_space_time
]
++
;
}
static
void
process_timestamps
(
struct
packet_timestamps
*
packet_ts
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
])
{
static
void
process_timestamps
(
packet_timestamps_t
*
packet_ts
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
])
{
char
data
[
256
];
struct
msghdr
msg
;
struct
iovec
entry
;
...
...
@@ -262,14 +265,18 @@ static void process_timestamps(struct packet_timestamps *packet_ts, int64_t hist
for
(
cmsg
=
CMSG_FIRSTHDR
(
&
msg
);
cmsg
;
cmsg
=
CMSG_NXTHDR
(
&
msg
,
cmsg
))
{
if
(
cmsg
->
cmsg_level
==
SOL_SOCKET
&&
cmsg
->
cmsg_type
==
SO_TIMESTAMPING
)
{
struct
timespec
*
stamp
=
(
struct
timespec
*
)
CMSG_DATA
(
cmsg
);
packet_ts
->
kernel_leave
=
ts_to_uint
(
*
stamp
);
packet_ts
->
leave_kernel
=
ts_to_uint
(
*
stamp
);
fill_histograms
(
packet_ts
,
histograms
);
}
else
{
#ifdef DEBUG
fprintf
(
stderr
,
"process_timestamps: level %d type %d"
,
cmsg
->
cmsg_level
,
cmsg
->
cmsg_type
);
#endif
}
}
}
...
...
@@ -304,18 +311,18 @@ static int process_socket_error_queue() {
tstamp
=
((
__u64
)
serr
->
ee_data
<<
32
)
+
serr
->
ee_info
;
switch
(
serr
->
ee_code
)
{
case
SO_EE_CODE_TXTIME_INVALID_PARAM
:
fprintf
(
stderr
,
"packet with tstamp %llu dropped due to invalid params
\n
"
,
tstamp
);
return
0
;
case
SO_EE_CODE_TXTIME_MISSED
:
fprintf
(
stderr
,
"packet with tstamp %llu dropped due to missed deadline
\n
"
,
tstamp
);
return
0
;
default:
return
-
1
;
case
SO_EE_CODE_TXTIME_INVALID_PARAM
:
fprintf
(
stderr
,
"packet with tstamp %llu dropped due to invalid params
\n
"
,
tstamp
);
return
0
;
case
SO_EE_CODE_TXTIME_MISSED
:
fprintf
(
stderr
,
"packet with tstamp %llu dropped due to missed deadline
\n
"
,
tstamp
);
return
0
;
default:
return
-
1
;
}
}
...
...
packet-exchange/src/send_packet.h
View file @
33d0cb10
#ifndef SEND_PACKET_H
#define SEND_PACKET_H
#include <stdint.h>
#include <stdio.h>
#include "utilities.h"
struct
packet_timestamps
{
uint64_t
user_enter_send
;
uint64_t
user_call_sendmsg
;
uint64_t
kernel_leave
;
};
void
init_udp_send
(
int
use_etf
,
int
use_timestamps
,
int
so_priority
,
char
*
network_if
,
size_t
tx_buffer_len
);
struct
packet_timestamps
send_udp_packet
(
int
use_etf
,
int
use_timestamps
,
uint64_t
txtime
,
const
char
*
server_ip
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
]);
void
init_udp_send
(
int
use_etf
,
int
use_timestamps
,
int
so_priority
,
char
*
network_if
,
size_t
tx_buffer_len
);
packet_timestamps_t
send_udp_packet
(
int
use_etf
,
int
use_timestamps
,
uint64_t
txtime
,
const
char
*
server_ip
,
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
]);
#endif
packet-exchange/src/server.c
View file @
33d0cb10
This diff is collapsed.
Click to expand it.
packet-exchange/src/utilities.c
View file @
33d0cb10
...
...
@@ -28,4 +28,3 @@ uint64_t calcdiff_ns(struct timespec t1, struct timespec t2) {
uint64_t
max
(
uint64_t
a
,
uint64_t
b
)
{
return
a
>
b
?
a
:
b
;
}
uint64_t
min
(
uint64_t
a
,
uint64_t
b
)
{
return
a
<
b
?
a
:
b
;
}
packet-exchange/src/utilities.h
View file @
33d0cb10
...
...
@@ -10,8 +10,14 @@
#define NSEC_PER_SEC UINT64_C(1000000000)
#define SERVER_PORT "50000"
#define SERVER_PORT_INT 50000
#define MAX_HIST_VAL 1000
#define NB_HISTOGRAMS 2
#define MAX_HIST_VAL 2000
#define NB_HISTOGRAMS 3
typedef
struct
packet_timestamps
{
uint64_t
enter_user_space
;
uint64_t
enter_kernel
;
uint64_t
leave_kernel
;
}
packet_timestamps_t
;
uint64_t
ts_to_uint
(
struct
timespec
t
);
void
add_ns
(
struct
timespec
*
t
,
uint64_t
ns
);
...
...
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