Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/netinet/libalias/perf.c
39488 views
1
/*
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright 2021 Lutz Donnerhacke
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
*
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above
13
* copyright notice, this list of conditions and the following
14
* disclaimer in the documentation and/or other materials provided
15
* with the distribution.
16
* 3. Neither the name of the copyright holder nor the names of its
17
* contributors may be used to endorse or promote products derived
18
* from this software without specific prior written permission.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
21
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
31
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
* SUCH DAMAGE.
33
*/
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <strings.h>
37
#include <sys/time.h>
38
#include "util.h"
39
#include <alias.h>
40
41
static void usage(void) __dead2;
42
43
#define timevalcmp(tv, uv, cmp) \
44
(((tv).tv_sec == (uv).tv_sec) \
45
? ((tv).tv_usec cmp (uv).tv_usec) \
46
: ((tv).tv_sec cmp (uv).tv_sec))
47
48
#define timevaldiff(n, o) (float) \
49
(((n).tv_sec - (o).tv_sec)*1000000l + \
50
((n).tv_usec - (o).tv_usec))
51
52
#define check_timeout() do { \
53
if (check_timeout_cnt++ > 1000) { \
54
check_timeout_cnt = 0; \
55
gettimeofday(&now, NULL); \
56
if (timevalcmp(now, timeout, >=)) \
57
goto out; \
58
} } while(0)
59
60
static void
61
usage(void) {
62
printf("Usage: perf [max_seconds [batch_size [random_size [attack_size [redir_size]]]]]\n");
63
exit(1);
64
}
65
66
int main(int argc, char ** argv)
67
{
68
struct libalias *la;
69
struct timeval timeout, now, start;
70
struct ip *p;
71
struct udphdr *u;
72
struct {
73
struct in_addr src, dst;
74
uint16_t sport, dport, aport;
75
} *batch;
76
struct {
77
unsigned long ok, fail;
78
} nat, usenat, unnat, random, attack;
79
int i, round, check_timeout_cnt = 0;
80
int max_seconds = 90, batch_size = 2000,
81
random_size = 1000, attack_size = 1000,
82
redir_size = 2000;
83
84
if (argc >= 2) {
85
char * end;
86
87
max_seconds = strtol(argv[1], &end, 10);
88
if (max_seconds < 2 || end[0] != '\0')
89
usage();
90
}
91
if (argc > 2 && (batch_size = atoi(argv[2])) < 0) usage();
92
if (argc > 3 && (random_size = atoi(argv[3])) < 0) usage();
93
if (argc > 4 && (attack_size = atoi(argv[4])) < 0) usage();
94
if (argc > 5 && (redir_size = atoi(argv[5])) < 0) usage();
95
96
printf("Running perfomance test with parameters:\n");
97
printf(" Maximum Runtime (max_seconds) = %d\n", max_seconds);
98
printf(" Amount of valid connections (batch_size) = %d\n", batch_size);
99
printf(" Amount of random, incoming packets (batch_size) = %d\n", random_size);
100
printf(" Repeat count of a random, incoming packet (attack_size) = %d\n", attack_size);
101
printf(" Amount of open port forwardings (redir_size) = %d\n", redir_size);
102
printf("\n");
103
104
if (NULL == (la = LibAliasInit(NULL))) {
105
perror("LibAliasInit");
106
return -1;
107
}
108
109
bzero(&nat, sizeof(nat));
110
bzero(&usenat, sizeof(usenat));
111
bzero(&unnat, sizeof(unnat));
112
bzero(&random, sizeof(random));
113
bzero(&attack, sizeof(attack));
114
115
LibAliasSetAddress(la, masq);
116
LibAliasSetMode(la, PKT_ALIAS_SAME_PORTS | PKT_ALIAS_DENY_INCOMING, ~0);
117
118
prv1.s_addr &= htonl(0xffff0000);
119
ext.s_addr &= htonl(0xffff0000);
120
121
for (i = 0; i < redir_size; i++) {
122
int aport = htons(rand_range(1000, 2000));
123
int sport = htons(rand_range(1000, 2000));
124
125
prv2.s_addr &= htonl(0xffff0000);
126
prv2.s_addr |= rand_range(0, 0xffff);
127
LibAliasRedirectPort(la, prv2, sport, ANY_ADDR, 0, masq, aport, IPPROTO_UDP);
128
}
129
130
p = ip_packet(0, 64);
131
u = set_udp(p, 0, 0);
132
133
if (NULL == (batch = calloc(batch_size, sizeof(*batch)))) {
134
perror("calloc(batch)");
135
return -1;
136
}
137
138
gettimeofday(&timeout, NULL);
139
timeout.tv_sec += max_seconds;
140
141
printf("RND SECOND newNAT RANDOM ATTACK useNAT\n");
142
for (round = 0; ; round++) {
143
int res, cnt;
144
145
printf("%3d ", round+1);
146
147
gettimeofday(&start, NULL);
148
printf("%6.1f ", max_seconds - timevaldiff(timeout, start)/1000000.0f);
149
for (cnt = i = 0; i < batch_size; i++, cnt++) {
150
batch[i].src.s_addr = prv1.s_addr | htonl(rand_range(0, 0xffff));
151
batch[i].dst.s_addr = ext.s_addr | htonl(rand_range(0, 0xffff));
152
batch[i].sport = rand_range(1000, 60000);
153
batch[i].dport = rand_range(1000, 60000);
154
155
p->ip_src = batch[i].src;
156
p->ip_dst = batch[i].dst;
157
u = set_udp(p, batch[i].sport, batch[i].dport);
158
159
res = LibAliasOut(la, p, 64);
160
batch[i].aport = htons(u->uh_sport);
161
162
if (res == PKT_ALIAS_OK &&
163
u->uh_dport == htons(batch[i].dport) &&
164
addr_eq(p->ip_dst, batch[i].dst) &&
165
addr_eq(p->ip_src, masq))
166
nat.ok++;
167
else
168
nat.fail++;
169
170
check_timeout();
171
}
172
gettimeofday(&now, NULL);
173
if (cnt > 0)
174
printf("%6.2f ", timevaldiff(now, start) / cnt);
175
else
176
printf("------ ");
177
178
start = now;
179
for (cnt = i = 0; i < random_size; i++, cnt++) {
180
p->ip_src.s_addr = ext.s_addr & htonl(0xfff00000);
181
p->ip_src.s_addr |= htonl(rand_range(0, 0xffff));
182
p->ip_dst = masq;
183
u = set_udp(p, rand_range(1, 0xffff), rand_range(1, 0xffff));
184
185
res = LibAliasIn(la, p, 64);
186
187
if (res == PKT_ALIAS_OK)
188
random.ok++;
189
else
190
random.fail++;
191
192
check_timeout();
193
}
194
gettimeofday(&now, NULL);
195
if (cnt > 0)
196
printf("%6.2f ", timevaldiff(now, start) / cnt);
197
else
198
printf("------ ");
199
200
start = now;
201
p->ip_src.s_addr = ext.s_addr & htonl(0xfff00000);
202
p->ip_src.s_addr |= htonl(rand_range(0, 0xffff));
203
p->ip_dst = masq;
204
u = set_udp(p, rand_range(1, 0xffff), rand_range(1, 0xffff));
205
for (cnt = i = 0; i < attack_size; i++, cnt++) {
206
res = LibAliasIn(la, p, 64);
207
208
if (res == PKT_ALIAS_OK)
209
attack.ok++;
210
else
211
attack.fail++;
212
213
check_timeout();
214
}
215
gettimeofday(&now, NULL);
216
if (cnt > 0)
217
printf("%6.2f ", timevaldiff(now, start) / cnt);
218
else
219
printf("------ ");
220
221
qsort(batch, batch_size, sizeof(*batch), randcmp);
222
223
gettimeofday(&start, NULL);
224
for (cnt = i = 0; i < batch_size; i++) {
225
int j;
226
227
/* random communication length */
228
for(j = rand_range(1, 150); j-- > 0; cnt++) {
229
int k;
230
231
/* a random flow out of rolling window */
232
k = rand_range(i, i + 25);
233
if (k >= batch_size)
234
k = i;
235
236
/* 10% outgoing, 90% incoming */
237
if (rand_range(0, 100) > 10) {
238
p->ip_src = batch[k].dst;
239
p->ip_dst = masq;
240
u = set_udp(p, batch[k].dport, batch[k].aport);
241
242
res = LibAliasIn(la, p, 64);
243
if (res == PKT_ALIAS_OK &&
244
u->uh_sport == htons(batch[k].dport) &&
245
u->uh_dport == htons(batch[k].sport) &&
246
addr_eq(p->ip_dst, batch[k].src) &&
247
addr_eq(p->ip_src, batch[k].dst))
248
unnat.ok++;
249
else
250
unnat.fail++;
251
} else {
252
p->ip_src = batch[k].src;
253
p->ip_dst = batch[k].dst;
254
u = set_udp(p, batch[k].sport, batch[k].dport);
255
256
res = LibAliasOut(la, p, 64);
257
if (res == PKT_ALIAS_OK &&
258
u->uh_sport == htons(batch[k].aport) &&
259
u->uh_dport == htons(batch[k].dport) &&
260
addr_eq(p->ip_dst, batch[k].dst) &&
261
addr_eq(p->ip_src, masq))
262
usenat.ok++;
263
else
264
usenat.fail++;
265
}
266
check_timeout();
267
}
268
}
269
gettimeofday(&now, NULL);
270
if (cnt > 0)
271
printf("%6.2f ", timevaldiff(now, start) / cnt);
272
else
273
printf("------ ");
274
275
printf("\n");
276
}
277
out:
278
printf("\n\n");
279
free(batch);
280
free(p);
281
282
printf("Results\n");
283
printf(" Rounds : %9u\n", round);
284
printf("newNAT ok : %9lu\n", nat.ok);
285
printf("newNAT fail: %9lu\n", nat.fail);
286
printf("useNAT ok : %9lu (out)\n", usenat.ok);
287
printf("useNAT fail: %9lu (out)\n", usenat.fail);
288
printf("useNAT ok : %9lu (in)\n", unnat.ok);
289
printf("useNAT fail: %9lu (in)\n", unnat.fail);
290
printf("RANDOM ok : %9lu\n", random.ok);
291
printf("RANDOM fail: %9lu\n", random.fail);
292
printf("ATTACK ok : %9lu\n", attack.ok);
293
printf("ATTACK fail: %9lu\n", attack.fail);
294
printf(" ---------\n");
295
printf(" Total: %9lu\n",
296
nat.ok + nat.fail +
297
unnat.ok + unnat.fail +
298
usenat.ok + usenat.fail +
299
random.ok + random.fail +
300
attack.ok + attack.fail);
301
302
gettimeofday(&start, NULL);
303
printf("\n Cleanup : ");
304
LibAliasUninit(la);
305
gettimeofday(&now, NULL);
306
printf("%.2fs\n", timevaldiff(now, start)/1000000l);
307
return (0);
308
}
309
310