Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
criu
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zhul
criu
Commits
d98c0ea6
Commit
d98c0ea6
authored
Aug 05, 2016
by
Pavel Emelyanov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
soccr/tcp: Fill actual connection info using the library
Signed-off-by:
Pavel Emelyanov
<
xemul@virtuozzo.com
>
parent
4fdc20ed
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
161 additions
and
138 deletions
+161
-138
sk-tcp.c
criu/sk-tcp.c
+28
-138
soccr.c
soccr/soccr.c
+133
-0
No files found.
criu/sk-tcp.c
View file @
d98c0ea6
#include <netinet/tcp.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#include <unistd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/mman.h>
...
@@ -29,11 +27,6 @@
...
@@ -29,11 +27,6 @@
#include "protobuf.h"
#include "protobuf.h"
#include "images/tcp-stream.pb-c.h"
#include "images/tcp-stream.pb-c.h"
#ifndef SIOCOUTQNSD
/* MAO - Define SIOCOUTQNSD ioctl if we don't have it */
#define SIOCOUTQNSD 0x894B
#endif
#ifndef CONFIG_HAS_TCP_REPAIR_WINDOW
#ifndef CONFIG_HAS_TCP_REPAIR_WINDOW
struct
tcp_repair_window
{
struct
tcp_repair_window
{
u32
snd_wl1
;
u32
snd_wl1
;
...
@@ -92,48 +85,6 @@ static int tcp_repair_on(int fd)
...
@@ -92,48 +85,6 @@ static int tcp_repair_on(int fd)
return
ret
;
return
ret
;
}
}
static
int
refresh_inet_sk
(
struct
inet_sk_desc
*
sk
,
struct
tcp_info
*
ti
)
{
int
size
;
if
(
dump_opt
(
sk
->
rfd
,
SOL_TCP
,
TCP_INFO
,
ti
))
{
pr_perror
(
"Failed to obtain TCP_INFO"
);
return
-
1
;
}
switch
(
ti
->
tcpi_state
)
{
case
TCP_ESTABLISHED
:
case
TCP_CLOSE
:
break
;
default:
pr_err
(
"Unknown state %d
\n
"
,
sk
->
state
);
return
-
1
;
}
if
(
ioctl
(
sk
->
rfd
,
SIOCOUTQ
,
&
size
)
==
-
1
)
{
pr_perror
(
"Unable to get size of snd queue"
);
return
-
1
;
}
sk
->
wqlen
=
size
;
if
(
ioctl
(
sk
->
rfd
,
SIOCOUTQNSD
,
&
size
)
==
-
1
)
{
pr_perror
(
"Unable to get size of unsent data"
);
return
-
1
;
}
sk
->
uwqlen
=
size
;
if
(
ioctl
(
sk
->
rfd
,
SIOCINQ
,
&
size
)
==
-
1
)
{
pr_perror
(
"Unable to get size of recv queue"
);
return
-
1
;
}
sk
->
rqlen
=
size
;
return
0
;
}
static
int
tcp_repair_establised
(
int
fd
,
struct
inet_sk_desc
*
sk
)
static
int
tcp_repair_establised
(
int
fd
,
struct
inet_sk_desc
*
sk
)
{
{
int
ret
;
int
ret
;
...
@@ -282,80 +233,10 @@ err_recv:
...
@@ -282,80 +233,10 @@ err_recv:
goto
err_buf
;
goto
err_buf
;
}
}
static
int
tcp_stream_get_options
(
int
sk
,
struct
tcp_info
*
ti
,
TcpStreamEntry
*
tse
)
{
int
ret
;
socklen_t
auxl
;
int
val
;
auxl
=
sizeof
(
tse
->
mss_clamp
);
ret
=
getsockopt
(
sk
,
SOL_TCP
,
TCP_MAXSEG
,
&
tse
->
mss_clamp
,
&
auxl
);
if
(
ret
<
0
)
goto
err_sopt
;
tse
->
opt_mask
=
ti
->
tcpi_options
;
if
(
ti
->
tcpi_options
&
TCPI_OPT_WSCALE
)
{
tse
->
snd_wscale
=
ti
->
tcpi_snd_wscale
;
tse
->
rcv_wscale
=
ti
->
tcpi_rcv_wscale
;
tse
->
has_rcv_wscale
=
true
;
}
if
(
ti
->
tcpi_options
&
TCPI_OPT_TIMESTAMPS
)
{
auxl
=
sizeof
(
val
);
ret
=
getsockopt
(
sk
,
SOL_TCP
,
TCP_TIMESTAMP
,
&
val
,
&
auxl
);
if
(
ret
<
0
)
goto
err_sopt
;
tse
->
has_timestamp
=
true
;
tse
->
timestamp
=
val
;
}
pr_info
(
"
\t
options: mss_clamp %x wscale %x tstamp %d sack %d
\n
"
,
(
int
)
tse
->
mss_clamp
,
ti
->
tcpi_options
&
TCPI_OPT_WSCALE
?
(
int
)
tse
->
snd_wscale
:
-
1
,
ti
->
tcpi_options
&
TCPI_OPT_TIMESTAMPS
?
1
:
0
,
ti
->
tcpi_options
&
TCPI_OPT_SACK
?
1
:
0
);
return
0
;
err_sopt:
pr_perror
(
"
\t
sockopt failed"
);
return
-
1
;
}
static
int
tcp_get_window
(
int
sk
,
TcpStreamEntry
*
tse
)
{
struct
tcp_repair_window
opt
;
socklen_t
optlen
=
sizeof
(
opt
);
if
(
!
kdat
.
has_tcp_window
)
return
0
;
if
(
getsockopt
(
sk
,
SOL_TCP
,
TCP_REPAIR_WINDOW
,
&
opt
,
&
optlen
))
{
pr_perror
(
"Unable to get window properties"
);
return
-
1
;
}
tse
->
has_snd_wl1
=
true
;
tse
->
has_snd_wnd
=
true
;
tse
->
has_max_window
=
true
;
tse
->
has_rcv_wnd
=
true
;
tse
->
has_rcv_wup
=
true
;
tse
->
snd_wl1
=
opt
.
snd_wl1
;
tse
->
snd_wnd
=
opt
.
snd_wnd
;
tse
->
max_window
=
opt
.
max_window
;
tse
->
rcv_wnd
=
opt
.
rcv_wnd
;
tse
->
rcv_wup
=
opt
.
rcv_wup
;
return
0
;
}
static
int
dump_tcp_conn_state
(
struct
inet_sk_desc
*
sk
)
static
int
dump_tcp_conn_state
(
struct
inet_sk_desc
*
sk
)
{
{
struct
libsoccr_sk
*
socr
=
sk
->
priv
;
struct
libsoccr_sk
*
socr
=
sk
->
priv
;
int
ret
,
aux
;
int
ret
,
aux
;
struct
tcp_info
ti
;
struct
cr_img
*
img
;
struct
cr_img
*
img
;
TcpStreamEntry
tse
=
TCP_STREAM_ENTRY__INIT
;
TcpStreamEntry
tse
=
TCP_STREAM_ENTRY__INIT
;
char
*
in_buf
,
*
out_buf
;
char
*
in_buf
,
*
out_buf
;
...
@@ -370,16 +251,40 @@ static int dump_tcp_conn_state(struct inet_sk_desc *sk)
...
@@ -370,16 +251,40 @@ static int dump_tcp_conn_state(struct inet_sk_desc *sk)
goto
err_r
;
goto
err_r
;
}
}
ret
=
refresh_inet_sk
(
sk
,
&
ti
);
tse
.
inq_len
=
data
.
inq_len
;
if
(
ret
<
0
)
tse
.
outq_len
=
data
.
outq_len
;
goto
err_r
;
tse
.
unsq_len
=
data
.
unsq_len
;
tse
.
has_unsq_len
=
true
;
tse
.
mss_clamp
=
data
.
mss_clamp
;
tse
.
opt_mask
=
data
.
opt_mask
;
if
(
tse
.
opt_mask
&
TCPI_OPT_WSCALE
)
{
tse
.
snd_wscale
=
data
.
snd_wscale
;
tse
.
rcv_wscale
=
data
.
rcv_wscale
;
tse
.
has_rcv_wscale
=
true
;
}
if
(
tse
.
opt_mask
&
TCPI_OPT_TIMESTAMPS
)
{
tse
.
timestamp
=
data
.
timestamp
;
tse
.
has_timestamp
=
true
;
}
if
(
data
.
flags
&
SOCCR_FLAGS_WINDOW
)
{
tse
.
has_snd_wl1
=
true
;
tse
.
has_snd_wnd
=
true
;
tse
.
has_max_window
=
true
;
tse
.
has_rcv_wnd
=
true
;
tse
.
has_rcv_wup
=
true
;
tse
.
snd_wl1
=
data
.
snd_wl1
;
tse
.
snd_wnd
=
data
.
snd_wnd
;
tse
.
max_window
=
data
.
max_window
;
tse
.
rcv_wnd
=
data
.
rcv_wnd
;
tse
.
rcv_wup
=
data
.
rcv_wup
;
}
/*
/*
* Read queue
* Read queue
*/
*/
pr_info
(
"Reading inq for socket
\n
"
);
pr_info
(
"Reading inq for socket
\n
"
);
tse
.
inq_len
=
sk
->
rqlen
;
ret
=
tcp_stream_get_queue
(
sk
->
rfd
,
TCP_RECV_QUEUE
,
ret
=
tcp_stream_get_queue
(
sk
->
rfd
,
TCP_RECV_QUEUE
,
&
tse
.
inq_seq
,
tse
.
inq_len
,
&
in_buf
);
&
tse
.
inq_seq
,
tse
.
inq_len
,
&
in_buf
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -390,26 +295,11 @@ static int dump_tcp_conn_state(struct inet_sk_desc *sk)
...
@@ -390,26 +295,11 @@ static int dump_tcp_conn_state(struct inet_sk_desc *sk)
*/
*/
pr_info
(
"Reading outq for socket
\n
"
);
pr_info
(
"Reading outq for socket
\n
"
);
tse
.
outq_len
=
sk
->
wqlen
;
tse
.
unsq_len
=
sk
->
uwqlen
;
tse
.
has_unsq_len
=
true
;
ret
=
tcp_stream_get_queue
(
sk
->
rfd
,
TCP_SEND_QUEUE
,
ret
=
tcp_stream_get_queue
(
sk
->
rfd
,
TCP_SEND_QUEUE
,
&
tse
.
outq_seq
,
tse
.
outq_len
,
&
out_buf
);
&
tse
.
outq_seq
,
tse
.
outq_len
,
&
out_buf
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
err_out
;
goto
err_out
;
/*
* Initial options
*/
pr_info
(
"Reading options for socket
\n
"
);
ret
=
tcp_stream_get_options
(
sk
->
rfd
,
&
ti
,
&
tse
);
if
(
ret
<
0
)
goto
err_opt
;
if
(
tcp_get_window
(
sk
->
rfd
,
&
tse
))
goto
err_opt
;
/*
/*
* TCP socket options
* TCP socket options
*/
*/
...
...
soccr/soccr.c
View file @
d98c0ea6
#include <netinet/tcp.h>
#include <netinet/tcp.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <linux/sockios.h>
#include "soccr.h"
#include "soccr.h"
#ifndef SIOCOUTQNSD
/* MAO - Define SIOCOUTQNSD ioctl if we don't have it */
#define SIOCOUTQNSD 0x894B
#endif
#ifndef TCP_REPAIR_WINDOW
#define TCP_REPAIR_WINDOW 29
#endif
struct
tcp_repair_window
{
__u32
snd_wl1
;
__u32
snd_wnd
;
__u32
max_window
;
__u32
rcv_wnd
;
__u32
rcv_wup
;
};
static
void
(
*
log
)(
unsigned
int
loglevel
,
const
char
*
format
,
...)
static
void
(
*
log
)(
unsigned
int
loglevel
,
const
char
*
format
,
...)
__attribute__
((
__format__
(
__printf__
,
2
,
3
)));
__attribute__
((
__format__
(
__printf__
,
2
,
3
)));
static
unsigned
int
log_level
=
0
;
static
unsigned
int
log_level
=
0
;
...
@@ -63,6 +84,107 @@ void libsoccr_resume(struct libsoccr_sk *sk)
...
@@ -63,6 +84,107 @@ void libsoccr_resume(struct libsoccr_sk *sk)
free
(
sk
);
free
(
sk
);
}
}
static
int
refresh_sk
(
struct
libsoccr_sk
*
sk
,
struct
libsoccr_sk_data
*
data
,
struct
tcp_info
*
ti
)
{
int
size
;
socklen_t
olen
=
sizeof
(
*
ti
);
if
(
getsockopt
(
sk
->
fd
,
SOL_TCP
,
TCP_INFO
,
ti
,
&
olen
)
||
olen
!=
sizeof
(
*
ti
))
{
loge
(
"Failed to obtain TCP_INFO"
);
return
-
1
;
}
switch
(
ti
->
tcpi_state
)
{
case
TCP_ESTABLISHED
:
case
TCP_CLOSE
:
break
;
default:
loge
(
"Unknown state %d
\n
"
,
ti
->
tcpi_state
);
return
-
1
;
}
if
(
ioctl
(
sk
->
fd
,
SIOCOUTQ
,
&
size
)
==
-
1
)
{
loge
(
"Unable to get size of snd queue"
);
return
-
1
;
}
data
->
outq_len
=
size
;
if
(
ioctl
(
sk
->
fd
,
SIOCOUTQNSD
,
&
size
)
==
-
1
)
{
loge
(
"Unable to get size of unsent data"
);
return
-
1
;
}
data
->
unsq_len
=
size
;
if
(
ioctl
(
sk
->
fd
,
SIOCINQ
,
&
size
)
==
-
1
)
{
loge
(
"Unable to get size of recv queue"
);
return
-
1
;
}
data
->
inq_len
=
size
;
return
0
;
}
static
int
get_stream_options
(
struct
libsoccr_sk
*
sk
,
struct
libsoccr_sk_data
*
data
,
struct
tcp_info
*
ti
)
{
int
ret
;
socklen_t
auxl
;
int
val
;
auxl
=
sizeof
(
data
->
mss_clamp
);
ret
=
getsockopt
(
sk
->
fd
,
SOL_TCP
,
TCP_MAXSEG
,
&
data
->
mss_clamp
,
&
auxl
);
if
(
ret
<
0
)
goto
err_sopt
;
data
->
opt_mask
=
ti
->
tcpi_options
;
if
(
ti
->
tcpi_options
&
TCPI_OPT_WSCALE
)
{
data
->
snd_wscale
=
ti
->
tcpi_snd_wscale
;
data
->
rcv_wscale
=
ti
->
tcpi_rcv_wscale
;
}
if
(
ti
->
tcpi_options
&
TCPI_OPT_TIMESTAMPS
)
{
auxl
=
sizeof
(
val
);
ret
=
getsockopt
(
sk
->
fd
,
SOL_TCP
,
TCP_TIMESTAMP
,
&
val
,
&
auxl
);
if
(
ret
<
0
)
goto
err_sopt
;
data
->
timestamp
=
val
;
}
return
0
;
err_sopt:
loge
(
"
\t
sockopt failed"
);
return
-
1
;
}
static
int
get_window
(
struct
libsoccr_sk
*
sk
,
struct
libsoccr_sk_data
*
data
)
{
struct
tcp_repair_window
opt
;
socklen_t
optlen
=
sizeof
(
opt
);
if
(
getsockopt
(
sk
->
fd
,
SOL_TCP
,
TCP_REPAIR_WINDOW
,
&
opt
,
&
optlen
))
{
/* Appeared since 4.8, but TCP_repair itself is since 3.11 */
if
(
errno
==
ENOPROTOOPT
)
return
0
;
loge
(
"Unable to get window properties"
);
return
-
1
;
}
data
->
flags
|=
SOCCR_FLAGS_WINDOW
;
data
->
snd_wl1
=
opt
.
snd_wl1
;
data
->
snd_wnd
=
opt
.
snd_wnd
;
data
->
max_window
=
opt
.
max_window
;
data
->
rcv_wnd
=
opt
.
rcv_wnd
;
data
->
rcv_wup
=
opt
.
rcv_wup
;
return
0
;
}
/*
/*
* This is how much data we've had in the initial libsoccr
* This is how much data we've had in the initial libsoccr
*/
*/
...
@@ -70,10 +192,21 @@ void libsoccr_resume(struct libsoccr_sk *sk)
...
@@ -70,10 +192,21 @@ void libsoccr_resume(struct libsoccr_sk *sk)
int
libsoccr_get_sk_data
(
struct
libsoccr_sk
*
sk
,
struct
libsoccr_sk_data
*
data
,
unsigned
data_size
)
int
libsoccr_get_sk_data
(
struct
libsoccr_sk
*
sk
,
struct
libsoccr_sk_data
*
data
,
unsigned
data_size
)
{
{
struct
tcp_info
ti
;
if
(
!
data
||
data_size
<
SOCR_DATA_MIN_SIZE
)
if
(
!
data
||
data_size
<
SOCR_DATA_MIN_SIZE
)
return
-
1
;
return
-
1
;
memset
(
data
,
0
,
data_size
);
memset
(
data
,
0
,
data_size
);
if
(
refresh_sk
(
sk
,
data
,
&
ti
))
return
-
2
;
if
(
get_stream_options
(
sk
,
data
,
&
ti
))
return
-
3
;
if
(
get_window
(
sk
,
data
))
return
-
4
;
return
sizeof
(
struct
libsoccr_sk_data
);
return
sizeof
(
struct
libsoccr_sk_data
);
}
}
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