mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-08-06 01:03:43 +00:00
tap-vsockd: if the client closes, be prepared to reconnect
In `connect` mode the client looping calling `connect` and `close` on a timer. This could result in the server accepting the connection and the client accidentally closing it immediately. This patch makes `tap-vsockd` keep trying to (re-)establish the connection. Note that daemonization is delayed until after the first successful negotiation, so attempts to send a packet afterwards should succeed. Signed-off-by: David Scott <dave.scott@docker.com>
This commit is contained in:
parent
67bc700af3
commit
b72e8de310
@ -77,8 +77,8 @@ void set_macaddr(const char *dev, uint8_t *mac) {
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Negotiate a vmnet connection, returns 0 on success and 1 on error. */
|
||||||
void negotiate(int fd, struct vif_info *vif)
|
int negotiate(int fd, struct vif_info *vif)
|
||||||
{
|
{
|
||||||
/* Negotiate with com.docker.slirp */
|
/* Negotiate with com.docker.slirp */
|
||||||
struct init_message *me = create_init_message();
|
struct init_message *me = create_init_message();
|
||||||
@ -105,9 +105,10 @@ void negotiate(int fd, struct vif_info *vif)
|
|||||||
if (read_vif_info(fd, vif) == -1) {
|
if (read_vif_info(fd, vif) == -1) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
return;
|
return 0;
|
||||||
err:
|
err:
|
||||||
fatal("Failed to negotiate with com.docker.slirp");
|
syslog(LOG_CRIT, "Failed to negotiate vmnet connection");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -175,28 +176,16 @@ static void* tap_to_vmnet(void *arg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a connection. Handshake with the com.docker.slirp process and start
|
/* Handle a connection by exchanging ethernet frames forever.
|
||||||
* exchanging ethernet frames between the socket and the tap device.
|
|
||||||
*/
|
*/
|
||||||
static void handle(int fd, char *tap, int tapfd)
|
static void handle(struct connection *connection)
|
||||||
{
|
{
|
||||||
struct connection connection;
|
|
||||||
pthread_t v2t, t2v;
|
pthread_t v2t, t2v;
|
||||||
|
|
||||||
connection.fd = fd;
|
if (pthread_create(&v2t, NULL, vmnet_to_tap, connection) != 0){
|
||||||
negotiate(fd, &connection.vif);
|
|
||||||
syslog(LOG_INFO, "VMNET VIF has MAC %02x:%02x:%02x:%02x:%02x:%02x",
|
|
||||||
connection.vif.mac[0], connection.vif.mac[1], connection.vif.mac[2],
|
|
||||||
connection.vif.mac[3], connection.vif.mac[4], connection.vif.mac[5]
|
|
||||||
);
|
|
||||||
|
|
||||||
set_macaddr(tap, &connection.vif.mac[0]);
|
|
||||||
connection.tapfd = tapfd;
|
|
||||||
|
|
||||||
if (pthread_create(&v2t, NULL, vmnet_to_tap, &connection) != 0){
|
|
||||||
fatal("Failed to create the vmnet_to_tap thread");
|
fatal("Failed to create the vmnet_to_tap thread");
|
||||||
}
|
}
|
||||||
if (pthread_create(&t2v, NULL, tap_to_vmnet, &connection) != 0){
|
if (pthread_create(&t2v, NULL, tap_to_vmnet, connection) != 0){
|
||||||
fatal("Failed to create the tap_to_vmnet thread");
|
fatal("Failed to create the tap_to_vmnet thread");
|
||||||
}
|
}
|
||||||
if (pthread_join(v2t, NULL) != 0){
|
if (pthread_join(v2t, NULL) != 0){
|
||||||
@ -400,19 +389,44 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
openlog(argv[0], log_flags, LOG_DAEMON);
|
openlog(argv[0], log_flags, LOG_DAEMON);
|
||||||
|
|
||||||
int sock = -1;
|
|
||||||
if (listen_flag) {
|
|
||||||
syslog(LOG_INFO, "starting in listening mode with serviceid=%s and tap=%s", serviceid, tap);
|
|
||||||
int lsocket = create_listening_socket(sid);
|
|
||||||
sock = accept_socket(lsocket);
|
|
||||||
} else {
|
|
||||||
syslog(LOG_INFO, "starting in connect mode with serviceid=%s and tap=%s", serviceid, tap);
|
|
||||||
sock = connect_socket(sid);
|
|
||||||
}
|
|
||||||
/* Bring up the tap device before we daemonize */
|
|
||||||
int tapfd = alloc_tap(tap);
|
int tapfd = alloc_tap(tap);
|
||||||
if (daemon_flag) daemonize(pidfile);
|
|
||||||
|
|
||||||
handle(sock, tap, tapfd);
|
struct connection connection;
|
||||||
exit(0);
|
connection.tapfd = tapfd;
|
||||||
|
|
||||||
|
int sock = -1;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (sock != -1) {
|
||||||
|
close(sock);
|
||||||
|
sock = -1;
|
||||||
|
}
|
||||||
|
if (listen_flag) {
|
||||||
|
syslog(LOG_INFO, "starting in listening mode with serviceid=%s and tap=%s", serviceid, tap);
|
||||||
|
int lsocket = create_listening_socket(sid);
|
||||||
|
sock = accept_socket(lsocket);
|
||||||
|
close(lsocket);
|
||||||
|
} else {
|
||||||
|
syslog(LOG_INFO, "starting in connect mode with serviceid=%s and tap=%s", serviceid, tap);
|
||||||
|
sock = connect_socket(sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.fd = sock;
|
||||||
|
if (negotiate(sock, &connection.vif) != 0) {
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
syslog(LOG_INFO, "VMNET VIF has MAC %02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
connection.vif.mac[0], connection.vif.mac[1], connection.vif.mac[2],
|
||||||
|
connection.vif.mac[3], connection.vif.mac[4], connection.vif.mac[5]
|
||||||
|
);
|
||||||
|
set_macaddr(tap, &connection.vif.mac[0]);
|
||||||
|
|
||||||
|
/* Daemonize after we've made our first reliable connection */
|
||||||
|
if (daemon_flag) {
|
||||||
|
daemon_flag = 0;
|
||||||
|
daemonize(pidfile);
|
||||||
|
}
|
||||||
|
handle(&connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user