Difference between revisions of "Libsoccr"
(→Example: use source tag) |
|||
(9 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | Libsoccr is | + | Libsoccr is a library that does [[TCP connection]] checkpoint and restore. |
+ | |||
+ | Libsoccr resides in criu source code (<code>soccr</code> subdirectory) and consists of an API header and a static library. | ||
+ | |||
+ | Libsoccr is available since CRIU {{criu|2.10}} release. | ||
== Overview == | == Overview == | ||
− | To checkpoint a TCP connection one should | + | To checkpoint a TCP connection, one should |
# ''pause'' a socket (referenced by descriptor) | # ''pause'' a socket (referenced by descriptor) | ||
Line 11: | Line 15: | ||
# close it | # close it | ||
− | To restore a connection one should | + | To restore a connection, one should |
# create a socket | # create a socket | ||
Line 23: | Line 27: | ||
== Data types == | == Data types == | ||
− | + | soccr/soccr.h declares three types: | |
− | ; < | + | ; <source lang="c" inline>struct libsoccr_sk</source> |
− | : | + | : An abstract handler returned by ''pausing'' routine that is used as an opaque identifier by the rest of the libsoccr calls |
− | ; < | + | ; <source lang="c" inline>struct libsoccr_sk_data</source> |
: A structure containing a set of 32-bit values that are returned by ''getter'' and that are to be passed '''as is''' to the ''setter'' call | : A structure containing a set of 32-bit values that are returned by ''getter'' and that are to be passed '''as is''' to the ''setter'' call | ||
− | ; < | + | ; <source lang="c" inline>struct libsoccr_addr</source> |
: A structure that defines soccaddr for a socket. It's used by set/get calls described further. | : A structure that defines soccaddr for a socket. It's used by set/get calls described further. | ||
Line 38: | Line 42: | ||
Inside the <code>libsoccr_sk_data</code> structure there's a special field called <code>flags</code> that gives information about the meaning of some other fields. Though it's not bad just to pass this structure as-is between libsoccr calls, doing some optimization based on flags is OK. | Inside the <code>libsoccr_sk_data</code> structure there's a special field called <code>flags</code> that gives information about the meaning of some other fields. Though it's not bad just to pass this structure as-is between libsoccr calls, doing some optimization based on flags is OK. | ||
− | + | Here are the flags that make sense: | |
− | ; < | + | ; <source lang="c" inline>SOCCR_FLAGS_WINDOW == 0x1</source> |
− | : When set indicates | + | : When set, indicates that fields <code>snd_wl1</code>, <code>snd_wnd</code>, <code>max_window</code>, <code>rcv_wnd</code> and <code>rcv_wup</code> contain some valuable data (0 is a valid value for any of these) |
== Calls == | == Calls == | ||
Line 47: | Line 51: | ||
=== Generic === | === Generic === | ||
− | ; < | + | ; <source lang="c" inline>struct libsoccr_sk *libsoccr_pause(int sk)</source> |
: Pauses the socket and returns a handler for further operations. Any data flow for this socket ''must be blocked by the caller'' before this call. | : Pauses the socket and returns a handler for further operations. Any data flow for this socket ''must be blocked by the caller'' before this call. | ||
− | ; < | + | ; <source lang="c" inline>void libsoccr_resume(struct libsoccr_sk *)</source> |
− | : Resumes the socket. Data flow unlock may happen before this. | + | : Resumes the socket and frees the handler. Data flow unlock may happen before this. |
+ | |||
+ | ; <source lang="c" inline>void libsoccr_release(struct libsoccr_sk *)</source> | ||
+ | : Only releases the handler and doesn't do anything with the socket itself. Use when saving the state and willing to kill the socket -- call <code>close()</code> on descriptor and this thing on the handler. | ||
− | ; < | + | ; <source lang="c" inline>void libsoccr_set_log(unsigned int level, void (*fn)(unsigned int level, const char *fmt, ...))</source> |
: Sets a function that will be called when libsoccr will want to print something on the screen. | : Sets a function that will be called when libsoccr will want to print something on the screen. | ||
=== Dump === | === Dump === | ||
− | ; < | + | ; <source lang="c" inline>int libsoccr_save(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, unsigned data_size)</source> |
: Fills in the <code>data</code> structure with the info get from paused socket. The <code>data_size</code> should be the size of the structure passed. The return code is the size of the structure really filled with data. | : Fills in the <code>data</code> structure with the info get from paused socket. The <code>data_size</code> should be the size of the structure passed. The return code is the size of the structure really filled with data. | ||
− | ; < | + | ; <source lang="c" inline>char *libsoccr_get_queue_bytes(struct libsoccr_sk *sk, int queue_id, unsigned flags)</source> |
− | : Returns a malloc()-ed array with the contents of the queue. The queue can be TCP_RECV_QUEUE or TCP_SEND_QUEUE. The amount of bytes in each is <code>data.inq_len</code> and <code>data.outq_len</code> respectively. The <code> | + | : Returns a malloc()-ed array with the contents of the queue. The queue can be TCP_RECV_QUEUE or TCP_SEND_QUEUE. The amount of bytes in each is <code>data.inq_len</code> and <code>data.outq_len</code> respectively. The <code>flags</code> may have <code>SOCCR_MEM_EXCL</code> bit set (see below). |
+ | |||
+ | ; <source lang="c" inline>union libsoccr_addr *libsoccr_get_addr(struct libsoccr_sk *sk, int self, unsigned flags)</source> (currently unimplemented and returns NULL) | ||
+ | : Returns address (self or peer) of the socket. The <code>flags</code> may have <code>SOCCR_MEM_EXCL</code> bit set (see below) | ||
=== Restore === | === Restore === | ||
− | ; < | + | ; <source lang="c" inline>int libsoccr_restore(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, unsigned data_size)</source> |
− | : Restores data on a socket from the <code>data</code> structure. Should be called before | + | : Restores data on a socket from the <code>data</code> structure. Should be called after the calls below, but before the "resume" one. |
− | ; < | + | ; <source lang="c" inline>int libsoccr_set_queue_bytes(struct libsoccr_sk *sk, int queue, char *buf, unsigned flags)</source> |
− | : | + | : Puts back the contents of the respective queue. The <code>flags</code> may contain <code>SOCCR_MEM_EXCL</code>. |
− | ; < | + | ; <source lang="c" inline>int libsoccr_set_addr(struct libsoccr_sk *sk, int self, union libsoccr_addr *, unsigned flags)</source> |
− | : | + | : Sets address (self or peer) of the socket. The <code>flags</code> may contain <code>SOCCR_MEM_EXCL</code>. |
− | + | == Flags == | |
− | + | Here are the flags accepted by various calls. | |
+ | ; <code>SOCCR_MEM_EXCL</code> | ||
+ | : Tells that the memory buffer set or get by the call is to be managed (and should be freed) by the ''receiving side''. In case of a get call the receiving side is the caller program, meaning it has to free() the buffer. In case of a set call the receiver is libsoccr, meaning libsoccr has to free() it. | ||
[[Category: Sub-projects]] | [[Category: Sub-projects]] | ||
[[Category: Sockets]] | [[Category: Sockets]] | ||
+ | == Example == | ||
+ | |||
+ | <source lang="c"> | ||
+ | /* Dump a tcp socket */ | ||
+ | |||
+ | dst_let = sizeof(addr); | ||
+ | if (getsockname(sock, (struct sockaddr *) &addr, &dst_let)) { | ||
+ | pr_perror("connect"); | ||
+ | return -1; | ||
+ | } | ||
+ | dst_let = sizeof(addr); | ||
+ | if (getpeername(sock, (struct sockaddr *) &dst, &dst_let)) { | ||
+ | pr_perror("connect"); | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | so = libsoccr_pause(sock); | ||
+ | |||
+ | dsize = libsoccr_save(so, &data, sizeof(data)); | ||
+ | if (dsize < 0) { | ||
+ | pr_perror("libsoccr_save"); | ||
+ | return -1; | ||
+ | } | ||
+ | close(sock); | ||
+ | |||
+ | |||
+ | /* Restore a tcp socket */ | ||
+ | rst = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | ||
+ | if (rst == -1) | ||
+ | return -1; | ||
+ | |||
+ | |||
+ | so_rst = libsoccr_pause(rst); | ||
+ | libsoccr_set_addr(so_rst, 1, &addr, 0); | ||
+ | libsoccr_set_addr(so_rst, 0, &dst, 0); | ||
+ | |||
+ | queue = libsoccr_get_queue_bytes(so, TCP_RECV_QUEUE, SOCCR_MEM_EXCL); | ||
+ | libsoccr_set_queue_bytes(so_rst, TCP_RECV_QUEUE, queue, SOCCR_MEM_EXCL); | ||
+ | queue = libsoccr_get_queue_bytes(so, TCP_SEND_QUEUE, SOCCR_MEM_EXCL); | ||
+ | libsoccr_set_queue_bytes(so_rst, TCP_SEND_QUEUE, queue, SOCCR_MEM_EXCL); | ||
+ | |||
+ | ret = libsoccr_restore(so_rst, &data, dsize); | ||
+ | if (ret) | ||
+ | return -1; | ||
+ | |||
+ | libsoccr_resume(so_rst); | ||
+ | libsoccr_resume(so); | ||
+ | </source> |
Latest revision as of 02:28, 26 January 2017
Libsoccr is a library that does TCP connection checkpoint and restore.
Libsoccr resides in criu source code (soccr
subdirectory) and consists of an API header and a static library.
Libsoccr is available since CRIU 2.10 "Brass Waxwing" release.
OverviewEdit
To checkpoint a TCP connection, one should
- pause a socket (referenced by descriptor)
- get socket data
- get contents of two queues
- (optionally) resume the socket
- close it
To restore a connection, one should
- create a socket
- pause one
- restore unbound data
- bind() and/or connect() socket to whatever addresses is appropriate using standard calls
- restore noq data
- put contents of two queues
- restore remaining data
Data typesEdit
soccr/soccr.h declares three types:
struct libsoccr_sk
- An abstract handler returned by pausing routine that is used as an opaque identifier by the rest of the libsoccr calls
struct libsoccr_sk_data
- A structure containing a set of 32-bit values that are returned by getter and that are to be passed as is to the setter call
struct libsoccr_addr
- A structure that defines soccaddr for a socket. It's used by set/get calls described further.
Data internalsEdit
Inside the libsoccr_sk_data
structure there's a special field called flags
that gives information about the meaning of some other fields. Though it's not bad just to pass this structure as-is between libsoccr calls, doing some optimization based on flags is OK.
Here are the flags that make sense:
SOCCR_FLAGS_WINDOW == 0x1
- When set, indicates that fields
snd_wl1
,snd_wnd
,max_window
,rcv_wnd
andrcv_wup
contain some valuable data (0 is a valid value for any of these)
CallsEdit
GenericEdit
struct libsoccr_sk *libsoccr_pause(int sk)
- Pauses the socket and returns a handler for further operations. Any data flow for this socket must be blocked by the caller before this call.
void libsoccr_resume(struct libsoccr_sk *)
- Resumes the socket and frees the handler. Data flow unlock may happen before this.
void libsoccr_release(struct libsoccr_sk *)
- Only releases the handler and doesn't do anything with the socket itself. Use when saving the state and willing to kill the socket -- call
close()
on descriptor and this thing on the handler.
void libsoccr_set_log(unsigned int level, void (*fn)(unsigned int level, const char *fmt, ...))
- Sets a function that will be called when libsoccr will want to print something on the screen.
DumpEdit
int libsoccr_save(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, unsigned data_size)
- Fills in the
data
structure with the info get from paused socket. Thedata_size
should be the size of the structure passed. The return code is the size of the structure really filled with data.
char *libsoccr_get_queue_bytes(struct libsoccr_sk *sk, int queue_id, unsigned flags)
- Returns a malloc()-ed array with the contents of the queue. The queue can be TCP_RECV_QUEUE or TCP_SEND_QUEUE. The amount of bytes in each is
data.inq_len
anddata.outq_len
respectively. Theflags
may haveSOCCR_MEM_EXCL
bit set (see below).
union libsoccr_addr *libsoccr_get_addr(struct libsoccr_sk *sk, int self, unsigned flags)
(currently unimplemented and returns NULL)- Returns address (self or peer) of the socket. The
flags
may haveSOCCR_MEM_EXCL
bit set (see below)
RestoreEdit
int libsoccr_restore(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, unsigned data_size)
- Restores data on a socket from the
data
structure. Should be called after the calls below, but before the "resume" one.
int libsoccr_set_queue_bytes(struct libsoccr_sk *sk, int queue, char *buf, unsigned flags)
- Puts back the contents of the respective queue. The
flags
may containSOCCR_MEM_EXCL
.
int libsoccr_set_addr(struct libsoccr_sk *sk, int self, union libsoccr_addr *, unsigned flags)
- Sets address (self or peer) of the socket. The
flags
may containSOCCR_MEM_EXCL
.
FlagsEdit
Here are the flags accepted by various calls.
SOCCR_MEM_EXCL
- Tells that the memory buffer set or get by the call is to be managed (and should be freed) by the receiving side. In case of a get call the receiving side is the caller program, meaning it has to free() the buffer. In case of a set call the receiver is libsoccr, meaning libsoccr has to free() it.
ExampleEdit
/* Dump a tcp socket */
dst_let = sizeof(addr);
if (getsockname(sock, (struct sockaddr *) &addr, &dst_let)) {
pr_perror("connect");
return -1;
}
dst_let = sizeof(addr);
if (getpeername(sock, (struct sockaddr *) &dst, &dst_let)) {
pr_perror("connect");
return -1;
}
so = libsoccr_pause(sock);
dsize = libsoccr_save(so, &data, sizeof(data));
if (dsize < 0) {
pr_perror("libsoccr_save");
return -1;
}
close(sock);
/* Restore a tcp socket */
rst = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (rst == -1)
return -1;
so_rst = libsoccr_pause(rst);
libsoccr_set_addr(so_rst, 1, &addr, 0);
libsoccr_set_addr(so_rst, 0, &dst, 0);
queue = libsoccr_get_queue_bytes(so, TCP_RECV_QUEUE, SOCCR_MEM_EXCL);
libsoccr_set_queue_bytes(so_rst, TCP_RECV_QUEUE, queue, SOCCR_MEM_EXCL);
queue = libsoccr_get_queue_bytes(so, TCP_SEND_QUEUE, SOCCR_MEM_EXCL);
libsoccr_set_queue_bytes(so_rst, TCP_SEND_QUEUE, queue, SOCCR_MEM_EXCL);
ret = libsoccr_restore(so_rst, &data, dsize);
if (ret)
return -1;
libsoccr_resume(so_rst);
libsoccr_resume(so);