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
10f80112
Commit
10f80112
authored
Jun 03, 2020
by
Joanne Hugé
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean up code
parent
a972e493
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
135 additions
and
102 deletions
+135
-102
packet-exchange/src/client.c
packet-exchange/src/client.c
+112
-80
packet-exchange/src/recv_packet.c
packet-exchange/src/recv_packet.c
+10
-9
packet-exchange/src/recv_packet.h
packet-exchange/src/recv_packet.h
+1
-1
packet-exchange/src/send_packet.c
packet-exchange/src/send_packet.c
+12
-12
No files found.
packet-exchange/src/client.c
View file @
10f80112
...
...
@@ -22,10 +22,7 @@
#include "send_packet.h"
#include "utilities.h"
// Enum and structs
enum
TSNTask
{
SEND_PACKET_TASK
,
RTT_TASK
};
// Structs
typedef
struct
thread_stat
{
int
nb_cycles
;
...
...
@@ -35,33 +32,27 @@ typedef struct thread_stat {
typedef
struct
thread_param
{
int
interval
;
int
priority
;
int
max_cycles
;
int
enable_affinity
;
int
enable_etf
;
int
enable_timestamps
;
int
enable_histograms
;
enum
TSNTask
tsn_task
;
int
sockfd
;
const
char
*
ip_address
;
char
network_if
[
256
];
int
priority
;
thread_stat_t
stats
;
}
thread_param_t
;
typedef
struct
main_param
{
int
refresh_rate
;
int
packet_priority
;
int
verbose
;
size_t
tx_buffer_len
;
}
main_param_t
;
typedef
struct
network_config
{
size_t
tx_buffer_len
;
char
ip_address
[
256
];
char
network_if
[
256
];
int
packet_priority
;
}
network_config_t
;
// Static functions
static
void
process_options
(
int
argc
,
char
*
argv
[],
thread_param_t
*
param
,
main_param_t
*
main_param
);
static
void
process_options
(
int
argc
,
char
*
argv
[]);
static
void
do_tsn_task
(
struct
thread_param
*
param
,
uint64_t
next_txtime
);
static
void
print_histograms
();
static
void
sigint_handler
(
int
sig_num
);
...
...
@@ -69,11 +60,22 @@ static void sigint_handler(int sig_num);
// Static variables
static
int64_t
histograms
[
NB_HISTOGRAMS
][
MAX_HIST_VAL
];
static
main_param_t
main_param
;
static
thread_param_t
*
param
;
static
network_config_t
network_config
;
static
int
enable_histograms
;
static
int
enable_affinity
;
static
int
enable_etf
;
static
int
enable_timestamps
;
enum
TSNTask
{
SEND_PACKET_TASK
,
RTT_TASK
};
static
enum
TSNTask
tsn_task
;
static
void
help
(
char
*
argv
[])
{
printf
(
"Usage: %s
[-abethgv] [-d BUF_LEN] [-f IF
] [-i USEC] [-l N] [-p PRIO] [-r USEC]
\n\n
"
,
argv
[
0
]);
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
"
);
printf
(
" -b Measure RTT
\n
"
);
printf
(
" -d BUF_LEN Set the length of tx buffer
\n
"
);
...
...
@@ -97,14 +99,15 @@ 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
;
cpu_set_t
mask
;
if
(
param
->
enable_affinity
)
{
// Set thread CPU affinity
// Set thread CPU affinity
if
(
enable_affinity
)
{
CPU_ZERO
(
&
mask
);
CPU_SET
(
1
,
&
mask
);
if
(
sched_setaffinity
(
0
,
sizeof
(
mask
),
&
mask
))
fprintf
(
stderr
,
"Could not set CPU affinity to CPU #1
\n
"
);
error
(
EXIT_FAILURE
,
errno
,
"Could not set CPU affinity to CPU #1
\n
"
);
}
// Set thread priority
...
...
@@ -120,9 +123,9 @@ static void *packet_sending_thread(void *p) {
next_txtime
+=
(
param
->
interval
)
/
2
;
// Packet sending loop
for
(
param
->
stats
.
nb_cycles
=
0
;;
param
->
stats
.
nb_cycles
++
)
{
for
(
stats
->
nb_cycles
=
0
;;
stats
->
nb_cycles
++
)
{
if
(
param
->
max_cycles
)
if
(
param
->
stats
.
nb_cycles
>=
param
->
max_cycles
)
if
(
stats
->
nb_cycles
>=
param
->
max_cycles
)
break
;
do_tsn_task
(
param
,
next_txtime
);
...
...
@@ -140,94 +143,113 @@ static void *packet_sending_thread(void *p) {
// Handles the IO and creates real time threads
int
main
(
int
argc
,
char
*
argv
[])
{
pthread_t
thread
;
thread_stat_t
*
stats
;
// Catch breaks with sigint_handler
signal
(
SIGINT
,
sigint_handler
);
param
=
malloc
(
sizeof
(
thread_param_t
));
stats
=
&
param
->
stats
;
// Default values
// Default
configuration
values
param
->
interval
=
100000
*
1000
;
param
->
max_cycles
=
0
;
param
->
priority
=
99
;
param
->
enable_affinity
=
0
;
param
->
enable_etf
=
0
;
param
->
enable_timestamps
=
0
;
param
->
enable_histograms
=
0
;
param
->
tsn_task
=
SEND_PACKET_TASK
;
enable_affinity
=
0
;
enable_etf
=
0
;
enable_timestamps
=
0
;
enable_histograms
=
0
;
tsn_task
=
SEND_PACKET_TASK
;
network_config
.
packet_priority
=
3
;
network_config
.
tx_buffer_len
=
1024
;
main_param
.
refresh_rate
=
50000
;
main_param
.
packet_priority
=
3
;
main_param
.
tx_buffer_len
=
1024
;
main_param
.
verbose
=
0
;
// Process bash options
process_options
(
argc
,
argv
,
param
,
&
main_param
);
process_options
(
argc
,
argv
);
if
(
param
->
enable_histograms
)
{
if
(
enable_histograms
)
{
// Init histograms
memset
((
int64_t
*
)
histograms
,
0
,
NB_HISTOGRAMS
*
MAX_HIST_VAL
);
memset
((
int64_t
*
)
histograms
,
0
,
NB_HISTOGRAMS
*
MAX_HIST_VAL
);
}
init_udp_send
(
param
->
enable_etf
,
param
->
enable_timestamps
,
main_param
.
packet_priority
,
param
->
network_if
,
main_param
.
tx_buffer_len
);
if
(
param
->
tsn_task
==
RTT_TASK
)
param
->
sockfd
=
init_udp_recv
();
// Initialize the UDP packet sending socket
init_udp_send
(
enable_etf
,
enable_timestamps
,
network_config
.
packet_priority
,
network_config
.
network_if
,
network_config
.
tx_buffer_len
);
usleep
(
10000
);
// Initialize the UDP packet receiving socket if RTT is measured
if
(
tsn_task
==
RTT_TASK
)
init_udp_recv
();
// Create the real time thread
if
(
pthread_create
(
&
thread
,
NULL
,
packet_sending_thread
,
(
void
*
)
param
))
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create thread"
);
// Verbose loop
for
(;;)
{
usleep
(
main_param
.
refresh_rate
);
if
(
main_param
.
verbose
)
{
if
(
param
->
tsn_task
==
RTT_TASK
)
{
printf
(
"RTT: %"
PRIu64
" (%d)
\n
"
,
param
->
stats
.
rtt
,
param
->
stats
.
nb_cycles
);
}
else
if
(
param
->
enable_timestamps
)
{
printf
(
"(%d)
\n
"
,
param
->
stats
.
nb_cycles
);
if
(
tsn_task
==
RTT_TASK
)
{
printf
(
"RTT: %"
PRIu64
" (%d)
\n
"
,
stats
->
rtt
,
stats
->
nb_cycles
);
}
else
if
(
enable_timestamps
)
{
printf
(
"(%d)
\n
"
,
stats
->
nb_cycles
);
printf
(
" Enter send_udp_packet timestamp: %"
PRIu64
"
\n
"
,
param
->
stats
.
packet_ts
.
user_enter_send
);
stats
->
packet_ts
.
user_enter_send
);
printf
(
" Call sendmsg timestamp : %"
PRIu64
"
\n
"
,
param
->
stats
.
packet_ts
.
user_call_sendmsg
);
stats
->
packet_ts
.
user_call_sendmsg
);
printf
(
" Leave kernel timestamp : %"
PRIu64
"
\n
"
,
param
->
stats
.
packet_ts
.
kernel_leave
);
stats
->
packet_ts
.
kernel_leave
);
}
}
if
(
param
->
max_cycles
)
if
(
param
->
max_cycles
==
param
->
stats
.
nb_cycles
)
if
(
param
->
max_cycles
==
stats
->
nb_cycles
)
break
;
}
if
(
param
->
enable_histograms
)
if
(
enable_histograms
)
print_histograms
();
exit
(
EXIT_SUCCESS
);
}
// Critical TSN task
static
void
do_tsn_task
(
struct
thread_param
*
param
,
uint64_t
next_txtime
)
{
struct
timespec
t1
,
t2
;
if
(
param
->
tsn_task
==
SEND_PACKET_TASK
)
{
// One way packet sending
if
(
tsn_task
==
SEND_PACKET_TASK
)
{
param
->
stats
.
packet_ts
=
send_udp_packet
(
param
->
enable_etf
,
param
->
enable_timestamps
,
next_txtime
,
param
->
ip_address
,
histograms
);
}
else
if
(
param
->
tsn_task
==
RTT_TASK
)
{
enable_etf
,
enable_timestamps
,
next_txtime
,
network_config
.
ip_address
,
histograms
);
// Round Trip Time measurement
}
else
if
(
tsn_task
==
RTT_TASK
)
{
clock_gettime
(
CLOCK_MONOTONIC
,
&
t1
);
send_udp_packet
(
param
->
enable_etf
,
param
->
enable_timestamps
,
next_txtime
,
param
->
ip_address
,
histograms
);
recv_udp_packet
(
param
->
sockfd
);
send_udp_packet
(
enable_etf
,
enable_timestamps
,
next_txtime
,
network_config
.
ip_address
,
histograms
);
recv_udp_packet
();
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
\"
],\
...
...
@@ -236,7 +258,7 @@ static void print_histograms() {
int
max_hist_val
=
0
;
for
(
int
i
=
0
;
i
<
NB_HISTOGRAMS
;
i
++
)
{
for
(
int
j
=
0
;
j
<
MAX_HIST_VAL
;
j
++
)
if
(
histograms
[
i
][
j
])
if
(
histograms
[
i
][
j
])
max_hist_val
=
j
>
max_hist_val
?
j
:
max_hist_val
;
}
...
...
@@ -259,7 +281,7 @@ static void print_histograms() {
uint64_t
duration
=
interval
*
param
->
stats
.
nb_cycles
;
int
duration_hour
=
duration
/
1000000
;
duration_hour
/=
3600
;
int
duration_minutes
=
duration
/
1000000
l
;
int
duration_minutes
=
duration
/
1000000
;
duration_minutes
/=
60
;
duration_minutes
-=
duration_hour
*
60
;
...
...
@@ -269,13 +291,16 @@ static void print_histograms() {
static
void
sigint_handler
(
int
sig_num
)
{
(
void
)
sig_num
;
if
(
param
->
enable_histograms
)
if
(
enable_histograms
)
print_histograms
();
exit
(
EXIT_SUCCESS
);
}
static
void
process_options
(
int
argc
,
char
*
argv
[],
thread_param_t
*
param
,
main_param_t
*
main_param
)
{
// Process bash options
static
void
process_options
(
int
argc
,
char
*
argv
[])
{
int
network_if_specified
=
0
;
for
(;;)
{
int
c
=
getopt
(
argc
,
argv
,
"abd:ef:ghi:l:p:q:r:tv"
);
...
...
@@ -284,26 +309,27 @@ static void process_options(int argc, char *argv[], thread_param_t *param,
switch
(
c
)
{
case
'a'
:
param
->
enable_affinity
=
1
;
enable_affinity
=
1
;
break
;
case
'b'
:
param
->
tsn_task
=
RTT_TASK
;
tsn_task
=
RTT_TASK
;
break
;
case
'd'
:
main_param
->
tx_buffer_len
=
atoi
(
optarg
);
if
(
main_param
->
tx_buffer_len
<
1
)
{
network_config
.
tx_buffer_len
=
atoi
(
optarg
);
if
(
network_config
.
tx_buffer_len
<
1
)
{
fprintf
(
stderr
,
"BUF_LEN should be greater than 1
\n
"
);
exit
(
EXIT_FAILURE
);
}
break
;
case
'e'
:
param
->
enable_etf
=
1
;
enable_etf
=
1
;
break
;
case
'f'
:
strcpy
(
param
->
network_if
,
optarg
);
network_if_specified
=
1
;
strcpy
(
network_config
.
network_if
,
optarg
);
break
;
case
'g'
:
param
->
enable_histograms
=
1
;
enable_histograms
=
1
;
break
;
case
'h'
:
help
(
argv
);
...
...
@@ -319,28 +345,34 @@ static void process_options(int argc, char *argv[], thread_param_t *param,
param
->
priority
=
atoi
(
optarg
);
break
;
case
'q'
:
main_param
->
packet_priority
=
atoi
(
optarg
);
network_config
.
packet_priority
=
atoi
(
optarg
);
break
;
case
'r'
:
main_param
->
refresh_rate
=
atoi
(
optarg
);
main_param
.
refresh_rate
=
atoi
(
optarg
);
break
;
case
't'
:
param
->
enable_timestamps
=
1
;
enable_timestamps
=
1
;
break
;
case
'v'
:
main_param
->
verbose
=
1
;
main_param
.
verbose
=
1
;
break
;
default:
}
}
if
(
!
network_if_specified
)
{
fprintf
(
stderr
,
"You need to specifiy an network interface
\n
"
);
help
(
argv
);
exit
(
EXIT_FAILURE
);
break
;
}
}
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
"
);
help
(
argv
);
exit
(
EXIT_FAILURE
);
}
param
->
ip_address
=
argv
[
optind
]
;
strcpy
(
network_config
.
ip_address
,
argv
[
optind
])
;
}
packet-exchange/src/recv_packet.c
View file @
10f80112
...
...
@@ -22,10 +22,11 @@
#define BUFFER_SIZE 1024
static
char
rx_buffer
[
BUFFER_SIZE
];
static
int
sock_fd
;
int
init_udp_recv
()
{
int
status
;
int
fd
=
-
1
;
int
sock_
fd
=
-
1
;
struct
addrinfo
hints
,
*
servinfo
,
*
servinfo_it
;
memset
(
&
hints
,
0
,
sizeof
hints
);
...
...
@@ -41,11 +42,11 @@ int init_udp_recv() {
for
(
servinfo_it
=
servinfo
;
servinfo_it
;
servinfo_it
=
servinfo_it
->
ai_next
)
{
fd
=
socket
(
servinfo
->
ai_family
,
servinfo
->
ai_socktype
,
sock_
fd
=
socket
(
servinfo
->
ai_family
,
servinfo
->
ai_socktype
,
servinfo
->
ai_protocol
);
if
(
bind
(
fd
,
servinfo_it
->
ai_addr
,
servinfo_it
->
ai_addrlen
)
==
-
1
)
{
close
(
fd
);
if
(
bind
(
sock_
fd
,
servinfo_it
->
ai_addr
,
servinfo_it
->
ai_addrlen
)
==
-
1
)
{
close
(
sock_
fd
);
continue
;
}
break
;
...
...
@@ -53,23 +54,23 @@ int init_udp_recv() {
freeaddrinfo
(
servinfo
);
if
(
fd
==
-
1
)
if
(
sock_
fd
==
-
1
)
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create receive socket"
);
printf
(
"waiting to receive...
\n
"
);
return
fd
;
return
sock_
fd
;
}
void
recv_udp_packet
(
int
fd
)
{
void
recv_udp_packet
()
{
#ifdef DEBUG
int
bytes_received
=
0
;
bytes_received
=
recvfrom
(
fd
,
rx_buffer
,
BUFFER_SIZE
-
1
,
0
,
NULL
,
NULL
);
bytes_received
=
recvfrom
(
sock_
fd
,
rx_buffer
,
BUFFER_SIZE
-
1
,
0
,
NULL
,
NULL
);
if
(
bytes_received
==
-
1
)
error
(
EXIT_FAILURE
,
errno
,
"Error while attempting to receive packets"
);
#else
recvfrom
(
fd
,
rx_buffer
,
BUFFER_SIZE
-
1
,
0
,
NULL
,
NULL
);
recvfrom
(
sock_
fd
,
rx_buffer
,
BUFFER_SIZE
-
1
,
0
,
NULL
,
NULL
);
#endif
}
packet-exchange/src/recv_packet.h
View file @
10f80112
...
...
@@ -2,6 +2,6 @@
#define RECV_PACKET
int
init_udp_recv
();
void
recv_udp_packet
(
int
fd
);
void
recv_udp_packet
();
#endif
packet-exchange/src/send_packet.c
View file @
10f80112
...
...
@@ -48,7 +48,7 @@ static int so_priority = 3;
static
struct
sock_txtime
sk_txtime
;
static
unsigned
char
*
tx_buffer
;
static
size_t
tx_buffer_len
;
static
int
fd
;
static
int
sock_
fd
;
static
int64_t
tai_offset
;
...
...
@@ -62,7 +62,7 @@ static int set_if(char *network_if) {
memset
(
&
ifreq
,
0
,
sizeof
(
ifreq
));
strncpy
(
ifreq
.
ifr_name
,
network_if
,
sizeof
(
ifreq
.
ifr_name
)
-
1
);
if
(
ioctl
(
fd
,
SIOCGIFINDEX
,
&
ifreq
))
if
(
ioctl
(
sock_
fd
,
SIOCGIFINDEX
,
&
ifreq
))
error
(
EXIT_FAILURE
,
errno
,
"ioctl SIOCGIFINDEX failed
\n
"
);
return
ifreq
.
ifr_ifindex
;
...
...
@@ -103,17 +103,17 @@ void init_udp_send(int use_etf, int use_timestamps, int packet_priority,
so_priority
=
packet_priority
;
fd
=
socket
(
PF_INET
,
SOCK_DGRAM
,
IPPROTO_UDP
);
if
(
fd
<
0
)
error
(
EXIT_FAILURE
,
errno
,
"Socket creation failed
\n
"
);
sock_
fd
=
socket
(
PF_INET
,
SOCK_DGRAM
,
IPPROTO_UDP
);
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
"
);
if
(
setsockopt
(
fd
,
SOL_SOCKET
,
SO_PRIORITY
,
&
so_priority
,
if
(
setsockopt
(
sock_
fd
,
SOL_SOCKET
,
SO_PRIORITY
,
&
so_priority
,
sizeof
(
so_priority
)))
error
(
EXIT_FAILURE
,
errno
,
"Couldn't set socket priority
\n
"
);
if
(
setsockopt
(
fd
,
SOL_SOCKET
,
SO_BINDTODEVICE
,
network_if
,
if
(
setsockopt
(
sock_
fd
,
SOL_SOCKET
,
SO_BINDTODEVICE
,
network_if
,
strlen
(
network_if
)))
error
(
EXIT_FAILURE
,
errno
,
"setsockopt SO_BINDTODEVICE failed
\n
"
);
...
...
@@ -121,12 +121,12 @@ void init_udp_send(int use_etf, int use_timestamps, int packet_priority,
sk_txtime
.
clockid
=
CLOCK_TAI
;
sk_txtime
.
flags
=
0
;
if
(
setsockopt
(
fd
,
SOL_SOCKET
,
SO_TXTIME
,
&
sk_txtime
,
sizeof
(
sk_txtime
)))
if
(
setsockopt
(
sock_
fd
,
SOL_SOCKET
,
SO_TXTIME
,
&
sk_txtime
,
sizeof
(
sk_txtime
)))
error
(
EXIT_FAILURE
,
errno
,
"setsockopt SO_TXTIME failed
\n
"
);
}
if
(
use_timestamps
)
{
if
(
setsockopt
(
fd
,
SOL_SOCKET
,
SO_TIMESTAMPING
,
&
so_timestamping_flags
,
if
(
setsockopt
(
sock_
fd
,
SOL_SOCKET
,
SO_TIMESTAMPING
,
&
so_timestamping_flags
,
sizeof
(
so_timestamping_flags
)))
error
(
EXIT_FAILURE
,
errno
,
"setsockopt SO_TIMESTAMPING failed
\n
"
);
}
...
...
@@ -157,7 +157,7 @@ struct packet_timestamps send_udp_packet(int use_etf, int use_timestamps,
struct
iovec
iov
;
int
sendmsgerr
;
int
res
;
struct
pollfd
poll_fd
=
{
fd
,
POLLPRI
,
0
};
struct
pollfd
poll_fd
=
{
sock_
fd
,
POLLPRI
,
0
};
struct
packet_timestamps
packet_ts
;
struct
timespec
ts
;
...
...
@@ -199,7 +199,7 @@ struct packet_timestamps send_udp_packet(int use_etf, int use_timestamps,
packet_ts
.
user_call_sendmsg
=
ts_to_uint
(
ts
);
}
sendmsgerr
=
sendmsg
(
fd
,
&
msg
,
0
);
sendmsgerr
=
sendmsg
(
sock_
fd
,
&
msg
,
0
);
if
(
sendmsgerr
<
0
)
error
(
EXIT_FAILURE
,
errno
,
"sendmsg failed, ret value: %d
\n
"
,
sendmsgerr
);
...
...
@@ -255,7 +255,7 @@ static void process_timestamps(struct packet_timestamps *packet_ts, int64_t hist
msg
.
msg_control
=
&
control
;
msg
.
msg_controllen
=
sizeof
(
control
);
if
(
recvmsg
(
fd
,
&
msg
,
MSG_ERRQUEUE
|
MSG_DONTWAIT
)
==
-
1
)
{
if
(
recvmsg
(
sock_
fd
,
&
msg
,
MSG_ERRQUEUE
|
MSG_DONTWAIT
)
==
-
1
)
{
fprintf
(
stderr
,
"recvmsg failed
\n
"
);
return
;
}
...
...
@@ -292,7 +292,7 @@ static int process_socket_error_queue() {
.
msg_control
=
msg_control
,
.
msg_controllen
=
sizeof
(
msg_control
)};
if
(
recvmsg
(
fd
,
&
msg
,
MSG_ERRQUEUE
)
==
-
1
)
{
if
(
recvmsg
(
sock_
fd
,
&
msg
,
MSG_ERRQUEUE
)
==
-
1
)
{
fprintf
(
stderr
,
"recvmsg failed"
);
return
-
1
;
}
...
...
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