1 /*
2 * Copyright (C) 2016-2025 Red Hat, Inc. All rights reserved.
3 *
4 * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
5 *
6 * This software licensed under GPL-2.0+
7 */
8
9 #include "config.h"
10
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16
17 #include "libknet.h"
18
19 #include "internals.h"
20 #include "netutils.h"
21 #include "test-common.h"
22
23 static int private_data;
24
25 static void sock_notify(void *pvt_data,
26 int datafd,
27 int8_t channel,
28 uint8_t tx_rx,
29 int error,
30 int errorno)
31 {
32 return;
33 }
34
35 static int dhost_filter_ret = 0;
36
37 static int dhost_filter(void *pvt_data,
38 const unsigned char *outdata,
39 ssize_t outdata_len,
40 uint8_t tx_rx,
41 knet_node_id_t this_host_id,
42 knet_node_id_t src_host_id,
43 int8_t *dst_channel,
44 knet_node_id_t *dst_host_ids,
45 size_t *dst_host_ids_entries)
46 {
47 dst_host_ids[0] = 0;
48
49 /*
50 * fatal fault
51 */
52 if (dhost_filter_ret < 0) {
53 return -1;
54 }
55
56 /*
57 * trigger EINVAL
58 * no ids found
59 */
60 if (dhost_filter_ret == 0) {
61 *dst_host_ids_entries = 0;
62 return 0;
63 }
64
65 /*
66 * send correct info back
67 */
68
69 if (dhost_filter_ret == 1) {
70 dst_host_ids[0] = 1;
71 *dst_host_ids_entries = 1;
72 return 0;
73 }
74
75 /*
76 * trigger E2BIG
77 * mcast destinations
78 */
79 if (dhost_filter_ret == 2) {
80 dst_host_ids[0] = 1;
81 *dst_host_ids_entries = 2;
82 return 0;
83 }
84
85 /*
86 * return mcast
87 */
88 if (dhost_filter_ret == 3) {
89 return 1;
90 }
91
92 return dhost_filter_ret;
93 }
94
95 static void test(void)
96 {
97 knet_handle_t knet_h1, knet_h[2];
98 int logfds[2];
99 int datafd = 0;
100 int8_t channel = 0;
101 char send_buff[KNET_MAX_PACKET_SIZE];
102 struct sockaddr_storage lo;
103 int res;
104
105 memset(send_buff, 0, sizeof(send_buff));
106
107 printf("Test knet_send_sync incorrect knet_h\n");
108
109 if ((!knet_send_sync(NULL, send_buff, KNET_MAX_PACKET_SIZE, channel)) || (errno != EINVAL)) {
110 printf("knet_send_sync accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
111 exit(FAIL);
112 }
113
114 setup_logpipes(logfds);
115
116 knet_h1 = knet_handle_start(logfds, KNET_LOG_DEBUG, knet_h);
117
118 printf("Test knet_send_sync with no send_buff\n");
119 FAIL_ON_SUCCESS(knet_send_sync(knet_h1, NULL, KNET_MAX_PACKET_SIZE, channel), EINVAL);
120
121 printf("Test knet_send_sync with invalid send_buff len (0)\n");
122 FAIL_ON_SUCCESS(knet_send_sync(knet_h1, send_buff, 0, channel), EINVAL);
123
124 printf("Test knet_send_sync with invalid send_buff len (> KNET_MAX_PACKET_SIZE)\n");
125 FAIL_ON_SUCCESS(knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE + 1, channel), EINVAL);
126
127 printf("Test knet_send_sync with invalid channel (-1)\n");
128 channel = -1;
129 FAIL_ON_SUCCESS(knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel), EINVAL);
130
131 printf("Test knet_send_sync with invalid channel (KNET_DATAFD_MAX)\n");
132 channel = KNET_DATAFD_MAX;
133 FAIL_ON_SUCCESS(knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel), EINVAL);
134
135 printf("Test knet_send_sync with no filter configured\n");
136 channel = 1;
|
(26) Event lock_acquire: |
Example 1: Calling "knet_send_sync" acquires lock "knet_handle.tx_mutex". [details] |
|
(27) Event example_lock_order: |
Example 1 (cont.): Calling "knet_handle_stop_everything" acquires lock "knet_handle.pmtud_mutex" while holding "knet_handle.tx_mutex". [details] |
| Also see events: |
[lock_acquire][lock_order] |
137 FAIL_ON_SUCCESS(knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel), ENETDOWN);
138 FAIL_ON_ERR(knet_handle_enable_filter(knet_h1, NULL, dhost_filter));
139
140
141 printf("Test knet_send_sync with unconfigured channel\n");
142 channel = 0;
143 FAIL_ON_SUCCESS(knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel), EINVAL);
144
145 printf("Test knet_send_sync with data forwarding disabled\n");
146 FAIL_ON_ERR(knet_handle_enable_sock_notify(knet_h1, &private_data, sock_notify));
147
148 datafd = 0;
149 channel = -1;
150
151 FAIL_ON_ERR(knet_handle_add_datafd(knet_h1, &datafd, &channel));
152
153 if ((knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel) == sizeof(send_buff)) || (errno != ECANCELED)) {
154 printf("knet_send_sync didn't detect datafwd disabled or returned incorrect error: %s\n", strerror(errno));
155 CLEAN_EXIT(FAIL);
156 }
157
158 printf("Test knet_send_sync with broken dst_host_filter\n");
159 FAIL_ON_ERR(knet_handle_setfwd(knet_h1, 1));
160 dhost_filter_ret = -1;
161 if ((knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel) == sizeof(send_buff)) || (errno != EFAULT)) {
162 printf("knet_send_sync didn't detect fatal error from dst_host_filter or returned incorrect error: %s\n", strerror(errno));
163 CLEAN_EXIT(FAIL);
164 }
165
166 printf("Test knet_send_sync with dst_host_filter returning no host_ids_entries\n");
167 dhost_filter_ret = 0;
168 if ((knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel) == sizeof(send_buff)) || (errno != EINVAL)) {
169 printf("knet_send_sync didn't detect 0 host_ids from dst_host_filter or returned incorrect error: %s\n", strerror(errno));
170 CLEAN_EXIT(FAIL);
171 }
172
173 printf("Test knet_send_sync with host down\n");
174 dhost_filter_ret = 1;
175 if ((knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel) == sizeof(send_buff)) || (errno != EHOSTDOWN)) {
176 printf("knet_send_sync didn't detect hostdown or returned incorrect error: %s\n", strerror(errno));
177 CLEAN_EXIT(FAIL);
178 }
179
180 printf("Test knet_send_sync with dst_host_filter returning too many host_ids_entries\n");
181 FAIL_ON_ERR(knet_host_add(knet_h1, 1));
182 FAIL_ON_ERR(_knet_link_set_config(knet_h1, 1, 0, KNET_TRANSPORT_UDP, 0, AF_INET, 0, &lo));
183 FAIL_ON_ERR(knet_link_set_enable(knet_h1, 1, 0, 1));
184 FAIL_ON_ERR(wait_for_host(knet_h1, 1, 10, logfds[0], stdout));
185 dhost_filter_ret = 2;
186 if ((knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel) == sizeof(send_buff)) || (errno != E2BIG)) {
187 printf("knet_send_sync didn't detect 2+ host_ids from dst_host_filter or returned incorrect error: %s\n", strerror(errno));
188 CLEAN_EXIT(FAIL);
189 }
190
191 printf("Test knet_send_sync with dst_host_filter returning mcast packets\n");
192 dhost_filter_ret = 3;
193 if ((knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel) == sizeof(send_buff)) || (errno != E2BIG)) {
194 printf("knet_send_sync didn't detect mcast packet from dst_host_filter or returned incorrect error: %s\n", strerror(errno));
195 CLEAN_EXIT(FAIL);
196 }
197
198
199 printf("Test knet_send_sync with valid data\n");
200 dhost_filter_ret = 1;
201 FAIL_ON_ERR(knet_send_sync(knet_h1, send_buff, KNET_MAX_PACKET_SIZE, channel));
202
203 FAIL_ON_ERR(knet_handle_setfwd(knet_h1, 0));
204
205 CLEAN_EXIT(CONTINUE);
206 }
207
208 int main(int argc, char *argv[])
209 {
210 test();
211
212 return PASS;
213 }
214