]> Git Repo - J-linux.git/blob - tools/testing/selftests/net/tcp_ao/seq-ext.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / testing / selftests / net / tcp_ao / seq-ext.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Check that after SEQ number wrap-around:
3  * 1. SEQ-extension has upper bytes set
4  * 2. TCP conneciton is alive and no TCPAOBad segments
5  * In order to test (2), the test doesn't just adjust seq number for a queue
6  * on a connected socket, but migrates it to another sk+port number, so
7  * that there won't be any delayed packets that will fail to verify
8  * with the new SEQ numbers.
9  */
10 #include <inttypes.h>
11 #include "aolib.h"
12
13 const unsigned int nr_packets = 1000;
14 const unsigned int msg_len = 1000;
15 const unsigned int quota = nr_packets * msg_len;
16 unsigned int client_new_port;
17
18 /* Move them closer to roll-over */
19 static void test_adjust_seqs(struct tcp_sock_state *img,
20                              struct tcp_ao_repair *ao_img,
21                              bool server)
22 {
23         uint32_t new_seq1, new_seq2;
24
25         /* make them roll-over during quota, but on different segments */
26         if (server) {
27                 new_seq1 = ((uint32_t)-1) - msg_len;
28                 new_seq2 = ((uint32_t)-1) - (quota - 2 * msg_len);
29         } else {
30                 new_seq1 = ((uint32_t)-1) - (quota - 2 * msg_len);
31                 new_seq2 = ((uint32_t)-1) - msg_len;
32         }
33
34         img->in.seq = new_seq1;
35         img->trw.snd_wl1 = img->in.seq - msg_len;
36         img->out.seq = new_seq2;
37         img->trw.rcv_wup = img->in.seq;
38 }
39
40 static int test_sk_restore(struct tcp_sock_state *img,
41                            struct tcp_ao_repair *ao_img, sockaddr_af *saddr,
42                            const union tcp_addr daddr, unsigned int dport,
43                            struct tcp_ao_counters *cnt)
44 {
45         int sk;
46
47         sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
48         if (sk < 0)
49                 test_error("socket()");
50
51         test_enable_repair(sk);
52         test_sock_restore(sk, img, saddr, daddr, dport);
53         if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0, daddr, -1, 100, 100))
54                 test_error("setsockopt(TCP_AO_ADD_KEY)");
55         test_ao_restore(sk, ao_img);
56
57         if (test_get_tcp_ao_counters(sk, cnt))
58                 test_error("test_get_tcp_ao_counters()");
59
60         test_disable_repair(sk);
61         test_sock_state_free(img);
62         return sk;
63 }
64
65 static void *server_fn(void *arg)
66 {
67         uint64_t before_good, after_good, after_bad;
68         struct tcp_ao_counters ao1, ao2;
69         struct tcp_sock_state img;
70         struct tcp_ao_repair ao_img;
71         sockaddr_af saddr;
72         ssize_t bytes;
73         int sk, lsk;
74
75         lsk = test_listen_socket(this_ip_addr, test_server_port, 1);
76
77         if (test_add_key(lsk, DEFAULT_TEST_PASSWORD, this_ip_dest, -1, 100, 100))
78                 test_error("setsockopt(TCP_AO_ADD_KEY)");
79
80         synchronize_threads(); /* 1: MKT added => connect() */
81
82         if (test_wait_fd(lsk, TEST_TIMEOUT_SEC, 0))
83                 test_error("test_wait_fd()");
84
85         sk = accept(lsk, NULL, NULL);
86         if (sk < 0)
87                 test_error("accept()");
88
89         synchronize_threads(); /* 2: accepted => send data */
90         close(lsk);
91
92         bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC);
93         if (bytes != quota) {
94                 if (bytes > 0)
95                         test_fail("server served: %zd", bytes);
96                 else
97                         test_fail("server returned: %zd", bytes);
98                 goto out;
99         }
100
101         before_good = netstat_get_one("TCPAOGood", NULL);
102
103         synchronize_threads(); /* 3: restore the connection on another port */
104
105         test_enable_repair(sk);
106         test_sock_checkpoint(sk, &img, &saddr);
107         test_ao_checkpoint(sk, &ao_img);
108         test_kill_sk(sk);
109 #ifdef IPV6_TEST
110         saddr.sin6_port = htons(ntohs(saddr.sin6_port) + 1);
111 #else
112         saddr.sin_port = htons(ntohs(saddr.sin_port) + 1);
113 #endif
114         test_adjust_seqs(&img, &ao_img, true);
115         synchronize_threads(); /* 4: dump finished */
116         sk = test_sk_restore(&img, &ao_img, &saddr, this_ip_dest,
117                              client_new_port, &ao1);
118
119         trace_ao_event_sne_expect(TCP_AO_SND_SNE_UPDATE, this_ip_addr,
120                         this_ip_dest, test_server_port + 1, client_new_port, 1);
121         trace_ao_event_sne_expect(TCP_AO_SND_SNE_UPDATE, this_ip_dest,
122                         this_ip_addr, client_new_port, test_server_port + 1, 1);
123         trace_ao_event_sne_expect(TCP_AO_RCV_SNE_UPDATE, this_ip_addr,
124                         this_ip_dest, test_server_port + 1, client_new_port, 1);
125         trace_ao_event_sne_expect(TCP_AO_RCV_SNE_UPDATE, this_ip_dest,
126                         this_ip_addr, client_new_port, test_server_port + 1, 1);
127         synchronize_threads(); /* 5: verify the connection during SEQ-number rollover */
128         bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC);
129         if (bytes != quota) {
130                 if (bytes > 0)
131                         test_fail("server served: %zd", bytes);
132                 else
133                         test_fail("server returned: %zd", bytes);
134         } else {
135                 test_ok("server alive");
136         }
137
138         synchronize_threads(); /* 6: verify counters after SEQ-number rollover */
139         if (test_get_tcp_ao_counters(sk, &ao2))
140                 test_error("test_get_tcp_ao_counters()");
141         after_good = netstat_get_one("TCPAOGood", NULL);
142
143         test_tcp_ao_counters_cmp(NULL, &ao1, &ao2, TEST_CNT_GOOD);
144
145         if (after_good <= before_good) {
146                 test_fail("TCPAOGood counter did not increase: %" PRIu64 " <= %" PRIu64,
147                           after_good, before_good);
148         } else {
149                 test_ok("TCPAOGood counter increased %" PRIu64 " => %" PRIu64,
150                         before_good, after_good);
151         }
152         after_bad = netstat_get_one("TCPAOBad", NULL);
153         if (after_bad)
154                 test_fail("TCPAOBad counter is non-zero: %" PRIu64, after_bad);
155         else
156                 test_ok("TCPAOBad counter didn't increase");
157         test_enable_repair(sk);
158         test_ao_checkpoint(sk, &ao_img);
159         if (ao_img.snd_sne && ao_img.rcv_sne) {
160                 test_ok("SEQ extension incremented: %u/%u",
161                         ao_img.snd_sne, ao_img.rcv_sne);
162         } else {
163                 test_fail("SEQ extension was not incremented: %u/%u",
164                           ao_img.snd_sne, ao_img.rcv_sne);
165         }
166
167         synchronize_threads(); /* 6: verified => closed */
168 out:
169         close(sk);
170         return NULL;
171 }
172
173 static void *client_fn(void *arg)
174 {
175         uint64_t before_good, after_good, after_bad;
176         struct tcp_ao_counters ao1, ao2;
177         struct tcp_sock_state img;
178         struct tcp_ao_repair ao_img;
179         sockaddr_af saddr;
180         int sk;
181
182         sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
183         if (sk < 0)
184                 test_error("socket()");
185
186         if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, -1, 100, 100))
187                 test_error("setsockopt(TCP_AO_ADD_KEY)");
188
189         synchronize_threads(); /* 1: MKT added => connect() */
190         if (test_connect_socket(sk, this_ip_dest, test_server_port) <= 0)
191                 test_error("failed to connect()");
192
193         synchronize_threads(); /* 2: accepted => send data */
194         if (test_client_verify(sk, msg_len, nr_packets, TEST_TIMEOUT_SEC)) {
195                 test_fail("pre-migrate verify failed");
196                 return NULL;
197         }
198
199         before_good = netstat_get_one("TCPAOGood", NULL);
200
201         synchronize_threads(); /* 3: restore the connection on another port */
202         test_enable_repair(sk);
203         test_sock_checkpoint(sk, &img, &saddr);
204         test_ao_checkpoint(sk, &ao_img);
205         test_kill_sk(sk);
206 #ifdef IPV6_TEST
207         client_new_port = ntohs(saddr.sin6_port) + 1;
208         saddr.sin6_port = htons(ntohs(saddr.sin6_port) + 1);
209 #else
210         client_new_port = ntohs(saddr.sin_port) + 1;
211         saddr.sin_port = htons(ntohs(saddr.sin_port) + 1);
212 #endif
213         test_adjust_seqs(&img, &ao_img, false);
214         synchronize_threads(); /* 4: dump finished */
215         sk = test_sk_restore(&img, &ao_img, &saddr, this_ip_dest,
216                              test_server_port + 1, &ao1);
217
218         synchronize_threads(); /* 5: verify the connection during SEQ-number rollover */
219         if (test_client_verify(sk, msg_len, nr_packets, TEST_TIMEOUT_SEC))
220                 test_fail("post-migrate verify failed");
221         else
222                 test_ok("post-migrate connection alive");
223
224         synchronize_threads(); /* 5: verify counters after SEQ-number rollover */
225         if (test_get_tcp_ao_counters(sk, &ao2))
226                 test_error("test_get_tcp_ao_counters()");
227         after_good = netstat_get_one("TCPAOGood", NULL);
228
229         test_tcp_ao_counters_cmp(NULL, &ao1, &ao2, TEST_CNT_GOOD);
230
231         if (after_good <= before_good) {
232                 test_fail("TCPAOGood counter did not increase: %" PRIu64 " <= %" PRIu64,
233                           after_good, before_good);
234         } else {
235                 test_ok("TCPAOGood counter increased %" PRIu64 " => %" PRIu64,
236                         before_good, after_good);
237         }
238         after_bad = netstat_get_one("TCPAOBad", NULL);
239         if (after_bad)
240                 test_fail("TCPAOBad counter is non-zero: %" PRIu64, after_bad);
241         else
242                 test_ok("TCPAOBad counter didn't increase");
243
244         synchronize_threads(); /* 6: verified => closed */
245         close(sk);
246
247         synchronize_threads(); /* don't race to exit: let server exit() */
248         return NULL;
249 }
250
251 int main(int argc, char *argv[])
252 {
253         test_init(8, server_fn, client_fn);
254         return 0;
255 }
This page took 0.041545 seconds and 4 git commands to generate.