Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/firecracker
Path: blob/main/tests/host_tools/vsock_helper.c
1956 views
1
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
// SPDX-License-Identifier: Apache-2.0
3
4
// This is a vsock helper tool, used by the Firecracker integration tests,
5
// to - well - test the virtio vsock device. It can be used to:
6
// 1. Run a forking echo server, that echoes back any data received from
7
// a client; and
8
// 2. Run a vsock echo client, that reads data from STDIN, sends it to an
9
// echo server, then forwards the server's reply to STDOUT.
10
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <sys/select.h>
14
#include <sys/wait.h>
15
#include <linux/vm_sockets.h>
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <stdint.h>
19
#include <string.h>
20
#include <unistd.h>
21
#include <stdio.h>
22
#include <errno.h>
23
24
25
#define BUF_SIZE (16 * 1024)
26
#define SERVER_ACCEPT_BACKLOG 128
27
28
29
int print_usage() {
30
fprintf(stderr, "Usage: ./vsock-helper {echosrv [-d] <port> | echo <cid> <port>}\n");
31
fprintf(stderr, "\n");
32
fprintf(stderr, " echosrv start a vsock echo server. The server will accept\n");
33
fprintf(stderr, " any incoming connection, and echo back any data\n");
34
fprintf(stderr, " received on it.\n");
35
fprintf(stderr, " -d can be used to daemonize the server.\n");
36
fprintf(stderr, "\n");
37
fprintf(stderr, " echo connect to an echo server, listening on CID:port.\n");
38
fprintf(stderr, " STDIN will be piped through to the echo server, and\n");
39
fprintf(stderr, " data coming from the server will pe sent to STDOUT.\n");
40
fprintf(stderr, "\n");
41
return -1;
42
}
43
44
int xfer(int src_fd, int dst_fd) {
45
char buf[BUF_SIZE];
46
int count = read(src_fd, buf, sizeof(buf));
47
48
if (!count) return 0;
49
if (count < 0) return -1;
50
51
int offset = 0;
52
do {
53
int written;
54
written = write(dst_fd, &buf[offset], count - offset);
55
if (written <= 0) return -1;
56
offset += written;
57
} while (offset < count);
58
59
return offset;
60
}
61
62
63
int run_echosrv(uint32_t port) {
64
65
struct sockaddr_vm vsock_addr = {
66
.svm_family = AF_VSOCK,
67
.svm_port = port,
68
.svm_cid = VMADDR_CID_ANY
69
};
70
71
int srv_sock = socket(AF_VSOCK, SOCK_STREAM, 0);
72
if (srv_sock < 0) {
73
perror("socket()");
74
return -1;
75
}
76
77
int res = bind(srv_sock, (struct sockaddr*)&vsock_addr, sizeof(struct sockaddr_vm));
78
if (res) {
79
perror("bind()");
80
return -1;
81
}
82
83
res = listen(srv_sock, SERVER_ACCEPT_BACKLOG);
84
if (res) {
85
perror("listen()");
86
return -1;
87
}
88
89
for (;;) {
90
struct sockaddr cl_addr;
91
socklen_t sockaddr_len = sizeof(cl_addr);
92
int cl_sock = accept(srv_sock, &cl_addr, &sockaddr_len);
93
if (cl_sock < 0) {
94
perror("accept()");
95
continue;
96
}
97
98
int pid = fork();
99
if (pid < 0) {
100
perror("fork()");
101
close(cl_sock);
102
continue;
103
}
104
105
if (!pid) {
106
int res;
107
do {
108
res = xfer(cl_sock, cl_sock);
109
} while (res > 0);
110
return res >= 0 ? 0 : -1;
111
}
112
113
close(cl_sock);
114
int cstatus;
115
waitpid(-1, &cstatus, WNOHANG);
116
printf("New client forked...\n");
117
}
118
119
return 0;
120
}
121
122
123
int run_echo(uint32_t cid, uint32_t port) {
124
125
int sock = socket(AF_VSOCK, SOCK_STREAM, 0);
126
if (sock < 0) {
127
perror("socket()");
128
return -1;
129
}
130
131
struct sockaddr_vm vsock_addr = {
132
.svm_family = AF_VSOCK,
133
.svm_port = port,
134
.svm_cid = cid
135
};
136
if (connect(sock, (struct sockaddr*)&vsock_addr, sizeof(vsock_addr)) < 0) {
137
perror("connect()");
138
return -1;
139
}
140
141
for (;;) {
142
int ping_cnt = xfer(STDIN_FILENO, sock);
143
if (!ping_cnt) break;
144
if (ping_cnt < 0) return -1;
145
146
int pong_cnt = 0;
147
while (pong_cnt < ping_cnt) {
148
int res = xfer(sock, STDOUT_FILENO);
149
if (res <= 0) return -1;
150
pong_cnt += res;
151
}
152
}
153
154
return 0;
155
}
156
157
158
int main(int argc, char **argv) {
159
160
if (argc < 3) {
161
return print_usage();
162
}
163
164
if (strcmp(argv[1], "echosrv") == 0) {
165
uint32_t port;
166
if (strcmp(argv[2], "-d") == 0) {
167
if (argc < 4) {
168
return print_usage();
169
}
170
port = atoi(argv[3]);
171
if (!port) {
172
return print_usage();
173
}
174
int pid = fork();
175
if (pid < 0) return -1;
176
if (pid) {
177
printf("Forked vsock echo daemon listening on port %d\n", port);
178
return 0;
179
}
180
setsid();
181
close(STDIN_FILENO);
182
close(STDOUT_FILENO);
183
}
184
else {
185
port = atoi(argv[2]);
186
if (!port) {
187
return print_usage();
188
}
189
}
190
return run_echosrv(port);
191
}
192
193
if (strcmp(argv[1], "echo") == 0) {
194
if (argc != 4) {
195
return print_usage();
196
}
197
uint32_t cid = atoi(argv[2]);
198
uint32_t port = atoi(argv[3]);
199
if (!cid || !port) {
200
return print_usage();
201
}
202
return run_echo(cid, port);
203
}
204
205
return print_usage();
206
}
207
208