vcl: fix epoll wait with indefinite timeout
[vpp.git] / src / plugins / hs_apps / vcl / vcl_test_protos.c
1 /*
2  * Copyright (c) 2021 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <hs_apps/vcl/vcl_test.h>
17
18 static int
19 vt_tcp_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
20 {
21   uint32_t flags, flen;
22   int rv;
23
24   ts->fd = vppcom_session_create (VPPCOM_PROTO_TCP, 0 /* is_nonblocking */);
25   if (ts->fd < 0)
26     {
27       vterr ("vppcom_session_create()", ts->fd);
28       return ts->fd;
29     }
30
31   /* Connect is blocking */
32   rv = vppcom_session_connect (ts->fd, endpt);
33   if (rv < 0)
34     {
35       vterr ("vppcom_session_connect()", rv);
36       return rv;
37     }
38
39   ts->read = vcl_test_read;
40   ts->write = vcl_test_write;
41   flags = O_NONBLOCK;
42   flen = sizeof (flags);
43   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
44   vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
45
46   return 0;
47 }
48
49 static int
50 vt_tcp_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
51 {
52   int rv;
53
54   ts->fd = vppcom_session_create (VPPCOM_PROTO_TCP, 1 /* is_nonblocking */);
55   if (ts->fd < 0)
56     {
57       vterr ("vppcom_session_create()", ts->fd);
58       return ts->fd;
59     }
60
61   rv = vppcom_session_bind (ts->fd, endpt);
62   if (rv < 0)
63     {
64       vterr ("vppcom_session_bind()", rv);
65       return rv;
66     }
67
68   rv = vppcom_session_listen (ts->fd, 10);
69   if (rv < 0)
70     {
71       vterr ("vppcom_session_listen()", rv);
72       return rv;
73     }
74
75   return 0;
76 }
77
78 static int
79 vt_tcp_accept (int listen_fd, vcl_test_session_t *ts)
80 {
81   int client_fd;
82
83   client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
84   if (client_fd < 0)
85     {
86       vterr ("vppcom_session_accept()", client_fd);
87       return client_fd;
88     }
89   ts->fd = client_fd;
90   ts->is_open = 1;
91   ts->read = vcl_test_read;
92   ts->write = vcl_test_write;
93
94   return 0;
95 }
96
97 static const vcl_test_proto_vft_t vcl_test_tcp = {
98   .open = vt_tcp_connect,
99   .listen = vt_tcp_listen,
100   .accept = vt_tcp_accept,
101 };
102
103 VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_TCP, vcl_test_tcp);
104
105 static int
106 vt_udp_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
107 {
108   uint32_t flags, flen;
109   int rv;
110
111   ts->fd = vppcom_session_create (VPPCOM_PROTO_UDP, 0 /* is_nonblocking */);
112   if (ts->fd < 0)
113     {
114       vterr ("vppcom_session_create()", ts->fd);
115       return ts->fd;
116     }
117
118   /* Connect is blocking */
119   rv = vppcom_session_connect (ts->fd, endpt);
120   if (rv < 0)
121     {
122       vterr ("vppcom_session_connect()", rv);
123       return rv;
124     }
125
126   ts->read = vcl_test_read;
127   ts->write = vcl_test_write;
128   flags = O_NONBLOCK;
129   flen = sizeof (flags);
130   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
131   vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
132
133   return 0;
134 }
135
136 static int
137 vt_udp_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
138 {
139   int rv;
140
141   ts->fd = vppcom_session_create (VPPCOM_PROTO_UDP, 1 /* is_nonblocking */);
142   if (ts->fd < 0)
143     {
144       vterr ("vppcom_session_create()", ts->fd);
145       return ts->fd;
146     }
147
148   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CONNECTED, 0, 0);
149
150   /* Listen is implicit */
151   rv = vppcom_session_bind (ts->fd, endpt);
152   if (rv < 0)
153     {
154       vterr ("vppcom_session_bind()", rv);
155       return rv;
156     }
157
158   return 0;
159 }
160
161 static int
162 vt_udp_accept (int listen_fd, vcl_test_session_t *ts)
163 {
164   int client_fd;
165
166   client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
167   if (client_fd < 0)
168     {
169       vterr ("vppcom_session_accept()", client_fd);
170       return client_fd;
171     }
172   ts->fd = client_fd;
173   ts->is_open = 1;
174   ts->read = vcl_test_read;
175   ts->write = vcl_test_write;
176
177   return 0;
178 }
179
180 static const vcl_test_proto_vft_t vcl_test_udp = {
181   .open = vt_udp_connect,
182   .listen = vt_udp_listen,
183   .accept = vt_udp_accept,
184 };
185
186 VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_UDP, vcl_test_udp);
187
188 /*
189  * TLS server cert and keys to be used for testing only
190  */
191 static char vcl_test_crt_rsa[] =
192   "-----BEGIN CERTIFICATE-----\r\n"
193   "MIID5zCCAs+gAwIBAgIJALeMYCEHrTtJMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD\r\n"
194   "VQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQK\r\n"
195   "DAVDaXNjbzEOMAwGA1UECwwFZmQuaW8xFjAUBgNVBAMMDXRlc3R0bHMuZmQuaW8x\r\n"
196   "IjAgBgkqhkiG9w0BCQEWE3ZwcC1kZXZAbGlzdHMuZmQuaW8wHhcNMTgwMzA1MjEx\r\n"
197   "NTEyWhcNMjgwMzAyMjExNTEyWjCBiTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNB\r\n"
198   "MREwDwYDVQQHDAhTYW4gSm9zZTEOMAwGA1UECgwFQ2lzY28xDjAMBgNVBAsMBWZk\r\n"
199   "LmlvMRYwFAYDVQQDDA10ZXN0dGxzLmZkLmlvMSIwIAYJKoZIhvcNAQkBFhN2cHAt\r\n"
200   "ZGV2QGxpc3RzLmZkLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\r\n"
201   "4C1k8a1DuStgggqT4o09fP9sJ2dC54bxhS/Xk2VEfaIZ222WSo4X/syRVfVy9Yah\r\n"
202   "cpI1zJ/RDxaZSFhgA+nPZBrFMsrULkrdAOpOVj8eDEp9JuWdO2ODSoFnCvLxcYWB\r\n"
203   "Yc5kHryJpEaGJl1sFQSesnzMFty/59ta0stk0Fp8r5NhIjWvSovGzPo6Bhz+VS2c\r\n"
204   "ebIZh4x1t2hHaFcgm0qJoJ6DceReWCW8w+yOVovTolGGq+bpb2Hn7MnRSZ2K2NdL\r\n"
205   "+aLXpkZbS/AODP1FF2vTO1mYL290LO7/51vJmPXNKSDYMy5EvILr5/VqtjsFCwRL\r\n"
206   "Q4jcM/+GeHSAFWx4qIv0BwIDAQABo1AwTjAdBgNVHQ4EFgQUWa1SOB37xmT53tZQ\r\n"
207   "aXuLLhRI7U8wHwYDVR0jBBgwFoAUWa1SOB37xmT53tZQaXuLLhRI7U8wDAYDVR0T\r\n"
208   "BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoUht13W4ya27NVzQuCMvqPWL3VM4\r\n"
209   "3xbPFk02FaGz/WupPu276zGlzJAZrbuDcQowwwU1Ni1Yygxl96s1c2M5rHDTrOKG\r\n"
210   "rK0hbkSFBo+i6I8u4HiiQ4rYmG0Hv6+sXn3of0HsbtDPGgWZoipPWDljPYEURu3e\r\n"
211   "3HRe/Dtsj9CakBoSDzs8ndWaBR+f4sM9Tk1cjD46Gq2T/qpSPXqKxEUXlzhdCAn4\r\n"
212   "twub17Bq2kykHpppCwPg5M+v30tHG/R2Go15MeFWbEJthFk3TZMjKL7UFs7fH+x2\r\n"
213   "wSonXb++jY+KmCb93C+soABBizE57g/KmiR2IxQ/LMjDik01RSUIaM0lLA==\r\n"
214   "-----END CERTIFICATE-----\r\n";
215 static uint32_t vcl_test_crt_rsa_len = sizeof (vcl_test_crt_rsa);
216
217 static char vcl_test_key_rsa[] =
218   "-----BEGIN PRIVATE KEY-----\r\n"
219   "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgLWTxrUO5K2CC\r\n"
220   "CpPijT18/2wnZ0LnhvGFL9eTZUR9ohnbbZZKjhf+zJFV9XL1hqFykjXMn9EPFplI\r\n"
221   "WGAD6c9kGsUyytQuSt0A6k5WPx4MSn0m5Z07Y4NKgWcK8vFxhYFhzmQevImkRoYm\r\n"
222   "XWwVBJ6yfMwW3L/n21rSy2TQWnyvk2EiNa9Ki8bM+joGHP5VLZx5shmHjHW3aEdo\r\n"
223   "VyCbSomgnoNx5F5YJbzD7I5Wi9OiUYar5ulvYefsydFJnYrY10v5otemRltL8A4M\r\n"
224   "/UUXa9M7WZgvb3Qs7v/nW8mY9c0pINgzLkS8guvn9Wq2OwULBEtDiNwz/4Z4dIAV\r\n"
225   "bHioi/QHAgMBAAECggEBAMzGipP8+oT166U+NlJXRFifFVN1DvdhG9PWnOxGL+c3\r\n"
226   "ILmBBC08WQzmHshPemBvR6DZkA1H23cV5JTiLWrFtC00CvhXsLRMrE5+uWotI6yE\r\n"
227   "iofybMroHvD6/X5R510UX9hQ6MHu5ShLR5VZ9zXHz5MpTmB/60jG5dLx+jgcwBK8\r\n"
228   "LuGv2YB/WCUwT9QJ3YU2eaingnXtz/MrFbkbltrqlnBdlD+kTtw6Yac9y1XuuQXc\r\n"
229   "BPeulLNDuPolJVWbUvDBZrpt2dXTgz8ws1sv+wCNE0xwQJsqW4Nx3QkpibUL9RUr\r\n"
230   "CVbKlNfa9lopT6nGKlgX69R/uH35yh9AOsfasro6w0ECgYEA82UJ8u/+ORah+0sF\r\n"
231   "Q0FfW5MTdi7OAUHOz16pUsGlaEv0ERrjZxmAkHA/VRwpvDBpx4alCv0Hc39PFLIk\r\n"
232   "nhSsM2BEuBkTAs6/GaoNAiBtQVE/hN7awNRWVmlieS0go3Y3dzaE9IUMyj8sPOFT\r\n"
233   "5JdJ6BM69PHKCkY3dKdnnfpFEuECgYEA68mRpteunF1mdZgXs+WrN+uLlRrQR20F\r\n"
234   "ZyMYiUCH2Dtn26EzA2moy7FipIIrQcX/j+KhYNGM3e7MU4LymIO29E18mn8JODnH\r\n"
235   "sQOXzBTsf8A4yIVMkcuQD3bfb0JiUGYUPOidTp2N7IJA7+6Yc3vQOyb74lnKnJoO\r\n"
236   "gougPT2wS+cCgYAn7muzb6xFsXDhyW0Tm6YJYBfRS9yAWEuVufINobeBZPSl2cN1\r\n"
237   "Jrnw+HlrfTNbrJWuJmjtZJXUXQ6cVp2rUbjutNyRV4vG6iRwEXYQ40EJdkr1gZpi\r\n"
238   "CHQhuShuuPih2MNAy7EEbM+sXrDjTBR3bFqzuHPzu7dp+BshCFX3lRfAAQKBgGQt\r\n"
239   "K5i7IhCFDjb/+3IPLgOAK7mZvsvZ4eXD33TQ2eZgtut1PXtBtNl17/b85uv293Fm\r\n"
240   "VDISVcsk3eLNS8zIiT6afUoWlxAwXEs0v5WRfjl4radkGvgGiJpJYvyeM67877RB\r\n"
241   "EDSKc/X8ESLfOB44iGvZUEMG6zJFscx9DgN25iQZAoGAbyd+JEWwdVH9/K3IH1t2\r\n"
242   "PBkZX17kNWv+iVM1WyFjbe++vfKZCrOJiyiqhDeEqgrP3AuNMlaaduC3VRC3G5oV\r\n"
243   "Mj1tlhDWQ/qhvKdCKNdIVQYDE75nw+FRWV8yYkHAnXYW3tNoweDIwixE0hkPR1bc\r\n"
244   "oEjPLVNtx8SOj/M4rhaPT3I=\r\n"
245   "-----END PRIVATE KEY-----\r\n";
246 static uint32_t vcl_test_key_rsa_len = sizeof (vcl_test_key_rsa);
247
248 static int
249 vt_add_cert_key_pair ()
250 {
251   vcl_test_main_t *vt = &vcl_test_main;
252   vppcom_cert_key_pair_t ckpair;
253   int ckp_index;
254
255   vtinf ("Adding tls certs ...");
256
257   ckpair.cert = vcl_test_crt_rsa;
258   ckpair.key = vcl_test_key_rsa;
259   ckpair.cert_len = vcl_test_crt_rsa_len;
260   ckpair.key_len = vcl_test_key_rsa_len;
261   ckp_index = vppcom_add_cert_key_pair (&ckpair);
262   if (ckp_index < 0)
263     {
264       vterr ("vppcom_add_cert_key_pair()", ckp_index);
265       return ckp_index;
266     }
267
268   vt->ckpair_index = ckp_index;
269   return 0;
270 }
271
272 static int
273 vt_tls_init (vcl_test_cfg_t *cfg)
274 {
275   return vt_add_cert_key_pair ();
276 }
277
278 static int
279 vt_tls_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
280 {
281   vcl_test_main_t *vt = &vcl_test_main;
282   uint32_t flags, flen, ckp_len;
283   int rv;
284
285   ts->fd = vppcom_session_create (VPPCOM_PROTO_TLS, 0 /* is_nonblocking */);
286   if (ts->fd < 0)
287     {
288       vterr ("vppcom_session_create()", ts->fd);
289       return ts->fd;
290     }
291
292   ckp_len = sizeof (vt->ckpair_index);
293   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
294                        &ckp_len);
295
296   /* Connect is blocking */
297   rv = vppcom_session_connect (ts->fd, endpt);
298   if (rv < 0)
299     {
300       vterr ("vppcom_session_connect()", rv);
301       return rv;
302     }
303
304   ts->read = vcl_test_read;
305   ts->write = vcl_test_write;
306   flags = O_NONBLOCK;
307   flen = sizeof (flags);
308   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
309   vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
310
311   return 0;
312 }
313
314 static int
315 vt_tls_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
316 {
317   vcl_test_main_t *vt = &vcl_test_main;
318   uint32_t ckp_len;
319   int rv;
320
321   ts->fd = vppcom_session_create (VPPCOM_PROTO_TLS, 1 /* is_nonblocking */);
322   if (ts->fd < 0)
323     {
324       vterr ("vppcom_session_create()", ts->fd);
325       return ts->fd;
326     }
327
328   ckp_len = sizeof (vt->ckpair_index);
329   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
330                        &ckp_len);
331
332   rv = vppcom_session_bind (ts->fd, endpt);
333   if (rv < 0)
334     {
335       vterr ("vppcom_session_bind()", rv);
336       return rv;
337     }
338
339   rv = vppcom_session_listen (ts->fd, 10);
340   if (rv < 0)
341     {
342       vterr ("vppcom_session_listen()", rv);
343       return rv;
344     }
345
346   return 0;
347 }
348
349 static int
350 vt_tls_accept (int listen_fd, vcl_test_session_t *ts)
351 {
352   int client_fd;
353
354   client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
355   if (client_fd < 0)
356     {
357       vterr ("vppcom_session_accept()", client_fd);
358       return client_fd;
359     }
360   ts->fd = client_fd;
361   ts->is_open = 1;
362   ts->read = vcl_test_read;
363   ts->write = vcl_test_write;
364
365   return 0;
366 }
367
368 static const vcl_test_proto_vft_t vcl_test_tls = {
369   .init = vt_tls_init,
370   .open = vt_tls_connect,
371   .listen = vt_tls_listen,
372   .accept = vt_tls_accept,
373 };
374
375 VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_TLS, vcl_test_tls);
376
377 static int
378 vt_dtls_init (vcl_test_cfg_t *cfg)
379 {
380   return vt_add_cert_key_pair ();
381 }
382
383 static int
384 vt_dtls_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
385 {
386   vcl_test_main_t *vt = &vcl_test_main;
387   uint32_t flags, flen, ckp_len;
388   int rv;
389
390   ts->fd = vppcom_session_create (VPPCOM_PROTO_DTLS, 0 /* is_nonblocking */);
391   if (ts->fd < 0)
392     {
393       vterr ("vppcom_session_create()", ts->fd);
394       return ts->fd;
395     }
396
397   ckp_len = sizeof (vt->ckpair_index);
398   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
399                        &ckp_len);
400
401   /* Connect is blocking */
402   rv = vppcom_session_connect (ts->fd, endpt);
403   if (rv < 0)
404     {
405       vterr ("vppcom_session_connect()", rv);
406       return rv;
407     }
408
409   ts->read = vcl_test_read;
410   ts->write = vcl_test_write;
411   flags = O_NONBLOCK;
412   flen = sizeof (flags);
413   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
414   vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
415
416   return 0;
417 }
418
419 static int
420 vt_dtls_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
421 {
422   vcl_test_main_t *vt = &vcl_test_main;
423   uint32_t ckp_len;
424   int rv;
425
426   ts->fd = vppcom_session_create (VPPCOM_PROTO_DTLS, 1 /* is_nonblocking */);
427   if (ts->fd < 0)
428     {
429       vterr ("vppcom_session_create()", ts->fd);
430       return ts->fd;
431     }
432
433   ckp_len = sizeof (vt->ckpair_index);
434   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
435                        &ckp_len);
436
437   rv = vppcom_session_bind (ts->fd, endpt);
438   if (rv < 0)
439     {
440       vterr ("vppcom_session_bind()", rv);
441       return rv;
442     }
443
444   rv = vppcom_session_listen (ts->fd, 10);
445   if (rv < 0)
446     {
447       vterr ("vppcom_session_listen()", rv);
448       return rv;
449     }
450
451   return 0;
452 }
453
454 static int
455 vt_dtls_accept (int listen_fd, vcl_test_session_t *ts)
456 {
457   int client_fd;
458
459   client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
460   if (client_fd < 0)
461     {
462       vterr ("vppcom_session_accept()", client_fd);
463       return client_fd;
464     }
465   ts->fd = client_fd;
466   ts->is_open = 1;
467   ts->read = vcl_test_read;
468   ts->write = vcl_test_write;
469
470   return 0;
471 }
472
473 static const vcl_test_proto_vft_t vcl_test_dtls = {
474   .init = vt_dtls_init,
475   .open = vt_dtls_connect,
476   .listen = vt_dtls_listen,
477   .accept = vt_dtls_accept,
478 };
479
480 VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_DTLS, vcl_test_dtls);
481
482 static int
483 vt_quic_init (vcl_test_cfg_t *cfg)
484 {
485   vcl_test_main_t *vt = &vcl_test_main;
486
487   if (cfg)
488     vt->cfg = *cfg;
489
490   return vt_add_cert_key_pair ();
491 }
492
493 static int
494 vt_quic_maybe_init_wrk (vcl_test_main_t *vt, vcl_test_wrk_t *wrk,
495                         vppcom_endpt_t *endpt)
496 {
497   uint32_t size, i, flags, flen, ckp_len;
498   vcl_test_session_t *tq;
499   int rv;
500
501   /* Test already initialized */
502   if (wrk->n_qsessions == vt->cfg.num_test_qsessions)
503     return 0;
504
505   /* Make sure pool is large enough */
506   if (!wrk->qsessions)
507     {
508       wrk->qsessions =
509         calloc (vt->cfg.num_test_qsessions, sizeof (vcl_test_session_t));
510     }
511   else
512     {
513       size = vt->cfg.num_test_qsessions * sizeof (vcl_test_session_t);
514       wrk->qsessions = realloc (wrk->qsessions, size);
515     }
516
517   if (!wrk->qsessions)
518     {
519       vterr ("failed to alloc Qsessions", -errno);
520       return errno;
521     }
522
523   for (i = 0; i < vt->cfg.num_test_qsessions; i++)
524     {
525       tq = &wrk->qsessions[i];
526       tq->fd =
527         vppcom_session_create (VPPCOM_PROTO_QUIC, 0 /* is_nonblocking */);
528       tq->session_index = i;
529       if (tq->fd < 0)
530         {
531           vterr ("vppcom_session_create()", tq->fd);
532           return tq->fd;
533         }
534
535       ckp_len = sizeof (vt->ckpair_index);
536       vppcom_session_attr (tq->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
537                            &ckp_len);
538
539       /* Connect is blocking */
540       rv = vppcom_session_connect (tq->fd, endpt);
541       if (rv < 0)
542         {
543           vterr ("vppcom_session_connect()", rv);
544           return rv;
545         }
546       flags = O_NONBLOCK;
547       flen = sizeof (flags);
548       vppcom_session_attr (tq->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
549       vtinf ("Test Qsession %d (fd %d) connected.", i, tq->fd);
550     }
551   wrk->n_qsessions = vt->cfg.num_test_qsessions;
552
553   return 0;
554 }
555
556 static int
557 vt_quic_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
558 {
559   vcl_test_main_t *vt = &vcl_test_main;
560   uint32_t wrk_index, flags, flen;
561   vcl_test_session_t *tq;
562   vcl_test_wrk_t *wrk;
563   int rv;
564
565   wrk_index = vcl_test_worker_index ();
566   wrk = &vt->wrk[wrk_index];
567
568   /* Make sure qsessions are initialized */
569   vt_quic_maybe_init_wrk (vt, wrk, endpt);
570
571   ts->fd = vppcom_session_create (VPPCOM_PROTO_QUIC, 0 /* is_nonblocking */);
572   if (ts->fd < 0)
573     {
574       vterr ("vppcom_session_create()", ts->fd);
575       return ts->fd;
576     }
577
578   /* Choose qession to use for stream */
579   tq = &wrk->qsessions[ts->session_index / vt->cfg.num_test_sessions_perq];
580
581   rv = vppcom_session_stream_connect (ts->fd, tq->fd);
582   if (rv < 0)
583     {
584       vterr ("vppcom_session_stream_connect()", rv);
585       return rv;
586     }
587
588   flags = O_NONBLOCK;
589   flen = sizeof (flags);
590   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
591
592   ts->read = vcl_test_read;
593   ts->write = vcl_test_write;
594
595   vtinf ("Test (quic stream) session %d (fd %d) connected.", ts->session_index,
596          ts->fd);
597
598   return 0;
599 }
600
601 static int
602 vt_quic_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
603 {
604   vcl_test_main_t *vt = &vcl_test_main;
605   uint32_t ckp_len;
606   int rv;
607
608   ts->fd = vppcom_session_create (VPPCOM_PROTO_QUIC, 1 /* is_nonblocking */);
609   if (ts->fd < 0)
610     {
611       vterr ("vppcom_session_create()", ts->fd);
612       return ts->fd;
613     }
614
615   ckp_len = sizeof (vt->ckpair_index);
616   vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
617                        &ckp_len);
618
619   rv = vppcom_session_bind (ts->fd, endpt);
620   if (rv < 0)
621     {
622       vterr ("vppcom_session_bind()", rv);
623       return rv;
624     }
625
626   rv = vppcom_session_listen (ts->fd, 10);
627   if (rv < 0)
628     {
629       vterr ("vppcom_session_listen()", rv);
630       return rv;
631     }
632
633   return 0;
634 }
635
636 static int
637 vt_quic_accept (int listen_fd, vcl_test_session_t *ts)
638 {
639   int client_fd;
640
641   client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
642   if (client_fd < 0)
643     {
644       vterr ("vppcom_session_accept()", client_fd);
645       return client_fd;
646     }
647   ts->fd = client_fd;
648   ts->is_open = 1;
649   ts->read = vcl_test_read;
650   ts->write = vcl_test_write;
651
652   return 0;
653 }
654
655 static int
656 vt_quic_close (vcl_test_session_t *ts)
657 {
658   int listener_fd = vppcom_session_listener (ts->fd);
659
660   if ((vppcom_session_n_accepted (listener_fd) == 0) &
661       vppcom_session_is_connectable_listener (listener_fd))
662     {
663       vtinf ("Connected Listener fd %x has no more sessions", listener_fd);
664       vppcom_session_close (listener_fd);
665     }
666
667   return 0;
668 }
669
670 static const vcl_test_proto_vft_t vcl_test_quic = {
671   .init = vt_quic_init,
672   .open = vt_quic_connect,
673   .listen = vt_quic_listen,
674   .accept = vt_quic_accept,
675   .close = vt_quic_close,
676 };
677
678 VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_QUIC, vcl_test_quic);
679
680 /*
681  * fd.io coding-style-patch-verification: ON
682  *
683  * Local Variables:
684  * eval: (c-set-style "gnu")
685  * End:
686  */