]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/test/lib/iscsi/param/param_ut.c
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / spdk / test / lib / iscsi / param / param_ut.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <stdint.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "spdk/scsi.h"
39
40 #include "spdk_cunit.h"
41
42 #include "../common.c"
43 #include "iscsi/param.c"
44
45 struct spdk_iscsi_globals g_spdk_iscsi;
46
47 struct spdk_iscsi_tgt_node *
48 spdk_iscsi_find_tgt_node(const char *target_name)
49 {
50 return NULL;
51 }
52
53 int
54 spdk_iscsi_tgt_node_access(struct spdk_iscsi_conn *conn,
55 struct spdk_iscsi_tgt_node *target,
56 const char *iqn, const char *addr)
57 {
58 return 0;
59 }
60
61 int
62 spdk_iscsi_send_tgts(struct spdk_iscsi_conn *conn, const char *iiqn,
63 const char *iaddr,
64 const char *tiqn, uint8_t *data, int alloc_len, int data_len)
65 {
66 return 0;
67 }
68
69 static void
70 burst_length_param_negotation(int FirstBurstLength, int MaxBurstLength,
71 int initialR2T)
72 {
73 struct spdk_iscsi_sess sess;
74 struct spdk_iscsi_conn conn;
75 struct iscsi_param *params;
76 char data[8192];
77 int rc;
78 int total, len;
79
80 total = 0;
81 params = NULL;
82
83 memset(&sess, 0, sizeof(sess));
84 memset(&conn, 0, sizeof(conn));
85 memset(data, 0, 8192);
86
87 sess.ExpCmdSN = 0;
88 sess.MaxCmdSN = 64;
89 sess.session_type = SESSION_TYPE_NORMAL;
90 sess.params = NULL;
91 sess.MaxBurstLength = 65536;
92 sess.InitialR2T = 1;
93 sess.FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH;
94 sess.MaxOutstandingR2T = 1;
95
96 /* set default params */
97 rc = spdk_iscsi_sess_params_init(&sess.params);
98 CU_ASSERT(rc == 0);
99
100 rc = spdk_iscsi_param_set_int(sess.params, "FirstBurstLength",
101 sess.FirstBurstLength);
102 CU_ASSERT(rc == 0);
103
104 rc = spdk_iscsi_param_set_int(sess.params, "MaxBurstLength",
105 sess.MaxBurstLength);
106 CU_ASSERT(rc == 0);
107
108 rc = spdk_iscsi_param_set(sess.params, "InitialR2T",
109 sess.InitialR2T ? "Yes" : "No");
110 CU_ASSERT(rc == 0);
111
112 conn.full_feature = 1;
113 conn.sess = &sess;
114 conn.MaxRecvDataSegmentLength = 65536;
115
116 rc = spdk_iscsi_conn_params_init(&conn.params);
117 CU_ASSERT(rc == 0);
118
119 /* construct the data*/
120 len = snprintf(data + total, 8192 - total, "%s=%d",
121 "FirstBurstLength", FirstBurstLength);
122 total += len + 1;
123
124 len = snprintf(data + total, 8192 - total, "%s=%d",
125 "MaxBurstLength", MaxBurstLength);
126 total += len + 1;
127
128 len = snprintf(data + total, 8192 - total, "%s=%d",
129 "InitialR2T", initialR2T);
130 total += len + 1;
131
132 /* add one extra NUL byte at the end to match real iSCSI params */
133 total++;
134
135 /* store incoming parameters */
136 rc = spdk_iscsi_parse_params(&params, data, total, false, NULL);
137 CU_ASSERT(rc == 0);
138
139 /* negotiate parameters */
140 rc = spdk_iscsi_negotiate_params(&conn, params,
141 data, 8192, rc);
142 CU_ASSERT(rc > 0);
143
144 rc = spdk_iscsi_copy_param2var(&conn);
145 CU_ASSERT(rc == 0);
146 CU_ASSERT(conn.sess->FirstBurstLength <= SPDK_ISCSI_FIRST_BURST_LENGTH);
147 CU_ASSERT(conn.sess->FirstBurstLength <= conn.sess->MaxBurstLength);
148 CU_ASSERT(conn.sess->MaxBurstLength <= SPDK_ISCSI_MAX_BURST_LENGTH);
149 CU_ASSERT(conn.sess->MaxOutstandingR2T == 1);
150
151 spdk_iscsi_param_free(sess.params);
152 spdk_iscsi_param_free(conn.params);
153 spdk_iscsi_param_free(params);
154 }
155
156 static void
157 param_negotiation_test(void)
158 {
159 burst_length_param_negotation(8192, 16384, 0);
160 burst_length_param_negotation(8192, 16384, 1);
161 burst_length_param_negotation(8192, 1024, 1);
162 burst_length_param_negotation(8192, 1024, 0);
163 burst_length_param_negotation(512, 1024, 1);
164 burst_length_param_negotation(512, 1024, 0);
165 }
166
167 static void
168 list_negotiation_test(void)
169 {
170 int add_param_value = 0;
171 struct iscsi_param param = {};
172 char *new_val;
173 char valid_list_buf[1024];
174 char in_val_buf[1024];
175
176 #define TEST_LIST(valid_list, in_val, expected_result) \
177 do { \
178 snprintf(valid_list_buf, sizeof(valid_list_buf), "%s", valid_list); \
179 snprintf(in_val_buf, sizeof(in_val_buf), "%s", in_val); \
180 new_val = spdk_iscsi_negotiate_param_list(&add_param_value, &param, valid_list_buf, in_val_buf, NULL); \
181 if (expected_result) { \
182 SPDK_CU_ASSERT_FATAL(new_val != NULL); \
183 CU_ASSERT_STRING_EQUAL(new_val, expected_result); \
184 } \
185 } while (0)
186
187 TEST_LIST("None", "None", "None");
188 TEST_LIST("CHAP,None", "None", "None");
189 TEST_LIST("CHAP,None", "CHAP", "CHAP");
190 TEST_LIST("KRB5,SRP,CHAP,None", "SRP,CHAP,None", "SRP");
191 TEST_LIST("KRB5,SRP,CHAP,None", "CHAP,SRP,None", "CHAP");
192 TEST_LIST("KRB5,SRP,CHAP,None", "SPKM1,SRP,CHAP,None", "SRP");
193 TEST_LIST("KRB5,SRP,None", "CHAP,None", "None");
194 }
195
196 #define PARSE(strconst, partial_enabled, partial_text) \
197 data = strconst; \
198 len = sizeof(strconst); \
199 rc = spdk_iscsi_parse_params(&params, data, len, partial_enabled, partial_text)
200
201 #define EXPECT_VAL(key, expected_value) \
202 { \
203 const char *val = spdk_iscsi_param_get_val(params, key); \
204 CU_ASSERT(val != NULL); \
205 if (val != NULL) { \
206 CU_ASSERT(strcmp(val, expected_value) == 0); \
207 } \
208 }
209
210 #define EXPECT_NULL(key) \
211 CU_ASSERT(spdk_iscsi_param_get_val(params, key) == NULL)
212
213 static void
214 parse_valid_test(void)
215 {
216 struct iscsi_param *params;
217 int rc;
218
219 params = NULL;
220 char *data;
221 int len;
222 char *partial_parameter = NULL;
223
224 /* simple test with a single key=value */
225 PARSE("Abc=def\0", false, NULL);
226 CU_ASSERT(rc == 0);
227 EXPECT_VAL("Abc", "def");
228
229 /* multiple key=value pairs */
230 PARSE("Aaa=bbbbbb\0Xyz=test\0", false, NULL);
231 CU_ASSERT(rc == 0);
232 EXPECT_VAL("Aaa", "bbbbbb");
233 EXPECT_VAL("Xyz", "test");
234
235 /* value with embedded '=' */
236 PARSE("A=b=c\0", false, NULL);
237 CU_ASSERT(rc == 0);
238 EXPECT_VAL("A", "b=c");
239
240 /* CHAP_C=AAAA.... with value length 8192 */
241 len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1/* null terminators */;
242 data = malloc(len);
243 SPDK_CU_ASSERT_FATAL(data != NULL);
244 memset(data, 'A', len);
245 strcpy(data, "CHAP_C");
246 data[6] = '=';
247 data[len - 1] = '\0';
248 rc = spdk_iscsi_parse_params(&params, data, len, false, NULL);
249 CU_ASSERT(rc == 0);
250 free(data);
251
252 /* partial parameter: value is partial*/
253 PARSE("C=AAA\0D=B", true, &partial_parameter);
254 SPDK_CU_ASSERT_FATAL(partial_parameter != NULL);
255 CU_ASSERT_STRING_EQUAL(partial_parameter, "D=B");
256 CU_ASSERT(rc == 0);
257 EXPECT_VAL("C", "AAA");
258 EXPECT_NULL("D");
259 PARSE("XXXX\0E=UUUU\0", false, &partial_parameter);
260 CU_ASSERT(rc == 0);
261 EXPECT_VAL("D", "BXXXX");
262 EXPECT_VAL("E", "UUUU");
263 CU_ASSERT_PTR_NULL(partial_parameter);
264
265 /* partial parameter: key is partial*/
266 PARSE("IAMAFAK", true, &partial_parameter);
267 CU_ASSERT_STRING_EQUAL(partial_parameter, "IAMAFAK");
268 CU_ASSERT(rc == 0);
269 EXPECT_NULL("IAMAFAK");
270 PARSE("EDKEY=TTTT\0F=IIII", false, &partial_parameter);
271 CU_ASSERT(rc == 0);
272 EXPECT_VAL("IAMAFAKEDKEY", "TTTT");
273 EXPECT_VAL("F", "IIII");
274 CU_ASSERT_PTR_NULL(partial_parameter);
275
276 /* Second partial parameter is the only parameter */
277 PARSE("OOOO", true, &partial_parameter);
278 CU_ASSERT_STRING_EQUAL(partial_parameter, "OOOO");
279 CU_ASSERT(rc == 0);
280 EXPECT_NULL("OOOO");
281 PARSE("LL=MMMM", false, &partial_parameter);
282 CU_ASSERT(rc == 0);
283 EXPECT_VAL("OOOOLL", "MMMM");
284 CU_ASSERT_PTR_NULL(partial_parameter);
285
286 spdk_iscsi_param_free(params);
287 }
288
289 static void
290 parse_invalid_test(void)
291 {
292 struct iscsi_param *params;
293 int rc;
294
295 params = NULL;
296 char *data;
297 int len;
298
299 /* key without '=' */
300 PARSE("Abc\0", false, NULL);
301 CU_ASSERT(rc != 0);
302 EXPECT_NULL("Abc");
303
304 /* multiple key=value pairs, one missing '=' */
305 PARSE("Abc=def\0Xyz\0Www=test\0", false, NULL);
306 CU_ASSERT(rc != 0);
307 EXPECT_VAL("Abc", "def");
308 EXPECT_NULL("Xyz");
309 EXPECT_NULL("Www");
310
311 /* empty key */
312 PARSE("=abcdef", false, NULL);
313 CU_ASSERT(rc != 0);
314 EXPECT_NULL("");
315
316 /* CHAP_C=AAAA.... with value length 8192 + 1 */
317 len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1 /* max value len + 1 */ +
318 1 /* null terminators */;
319 data = malloc(len);
320 SPDK_CU_ASSERT_FATAL(data != NULL);
321 memset(data, 'A', len);
322 strcpy(data, "CHAP_C");
323 data[6] = '=';
324 data[len - 1] = '\0';
325 rc = spdk_iscsi_parse_params(&params, data, len, false, NULL);
326 free(data);
327 CU_ASSERT(rc != 0);
328 EXPECT_NULL("CHAP_C");
329
330 /* Test simple value, length of value bigger than 255*/
331 len = strlen("A=") + ISCSI_TEXT_MAX_SIMPLE_VAL_LEN + 1 /* max simple value len + 1 */ +
332 1 /* null terminators */;
333 data = malloc(len);
334 SPDK_CU_ASSERT_FATAL(data != NULL);
335 memset(data, 'A', len);
336 data[1] = '=';
337 data[len - 1] = '\0';
338 rc = spdk_iscsi_parse_params(&params, data, len, false, NULL);
339 free(data);
340 CU_ASSERT(rc != 0);
341 EXPECT_NULL("A");
342
343 /* key length bigger than 63 */
344 len = ISCSI_TEXT_MAX_KEY_LEN + 1 /*max key length + 1*/ + 1 /* = */ + 1 /* A */ +
345 1/* null terminators */;
346 data = malloc(len);
347 SPDK_CU_ASSERT_FATAL(data != NULL);
348 memset(data, 'A', len);
349 data[64] = '=';
350 data[len - 1] = '\0';
351 rc = spdk_iscsi_parse_params(&params, data, len, false, NULL);
352 free(data);
353 CU_ASSERT(rc != 0);
354 EXPECT_NULL("A");
355
356 /* duplicated key */
357 PARSE("B=BB", false, NULL);
358 CU_ASSERT(rc == 0);
359 PARSE("B=BBBB", false, NULL);
360 CU_ASSERT(rc != 0);
361 EXPECT_VAL("B", "BB");
362
363 spdk_iscsi_param_free(params);
364 }
365
366 int
367 main(int argc, char **argv)
368 {
369 CU_pSuite suite = NULL;
370 unsigned int num_failures;
371
372 if (CU_initialize_registry() != CUE_SUCCESS) {
373 return CU_get_error();
374 }
375
376 suite = CU_add_suite("iscsi_suite", NULL, NULL);
377 if (suite == NULL) {
378 CU_cleanup_registry();
379 return CU_get_error();
380 }
381
382 if (
383 CU_add_test(suite, "param negotiation test",
384 param_negotiation_test) == NULL ||
385 CU_add_test(suite, "list negotation test",
386 list_negotiation_test) == NULL ||
387 CU_add_test(suite, "parse valid test",
388 parse_valid_test) == NULL ||
389 CU_add_test(suite, "parse invalid test",
390 parse_invalid_test) == NULL
391 ) {
392 CU_cleanup_registry();
393 return CU_get_error();
394 }
395
396 CU_basic_set_mode(CU_BRM_VERBOSE);
397 CU_basic_run_tests();
398 num_failures = CU_get_number_of_failures();
399 CU_cleanup_registry();
400 return num_failures;
401 }