1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
|
From 7a2dd92a527c1f5ee79239d93b792dc9a9758e27 Mon Sep 17 00:00:00 2001
From: liuxu <liuxu156@huawei.com>
Date: Tue, 7 Nov 2023 20:38:22 +0800
Subject: [PATCH 04/14] network:support version opt
---
.../network/cni_operator/cni_operate.c | 16 +++
.../network/cni_operator/cni_operate.h | 3 +
.../cni_operator/libcni/invoke/libcni_exec.c | 86 +++++++++++++-
.../cni_operator/libcni/invoke/libcni_exec.h | 2 +
.../libcni/invoke/libcni_result_parse.c | 29 +++++
.../libcni/invoke/libcni_result_parse.h | 6 +
.../network/cni_operator/libcni/libcni_api.c | 106 ++++++++++++++++++
.../network/cni_operator/libcni/libcni_api.h | 8 +-
.../cni_operator/libcni/libcni_result_type.c | 18 +++
.../cni_operator/libcni/libcni_result_type.h | 12 ++
.../modules/network/native/adaptor_native.c | 3 +-
11 files changed, 281 insertions(+), 8 deletions(-)
diff --git a/src/daemon/modules/network/cni_operator/cni_operate.c b/src/daemon/modules/network/cni_operator/cni_operate.c
index 62249f18..6db6db51 100644
--- a/src/daemon/modules/network/cni_operator/cni_operate.c
+++ b/src/daemon/modules/network/cni_operator/cni_operate.c
@@ -926,6 +926,22 @@ out:
return ret;
}
+int version_network_plane(const struct cni_network_list_conf *list,
+ struct cni_version_info_list **result_version_list)
+{
+ if (list == NULL || list->list == NULL) {
+ ERROR("Invalid input params");
+ return -1;
+ }
+
+ if (cni_version_network_list(list, result_version_list) != 0) {
+ ERROR("Version CNI network failed");
+ return -1;
+ }
+
+ return 0;
+}
+
int detach_loopback(const char *id, const char *netns)
{
int ret = 0;
diff --git a/src/daemon/modules/network/cni_operator/cni_operate.h b/src/daemon/modules/network/cni_operator/cni_operate.h
index 150c1154..7750ff00 100644
--- a/src/daemon/modules/network/cni_operator/cni_operate.h
+++ b/src/daemon/modules/network/cni_operator/cni_operate.h
@@ -61,6 +61,9 @@ int detach_network_plane(const struct cni_manager *manager, const struct cni_net
int check_network_plane(const struct cni_manager *manager, const struct cni_network_list_conf *list,
struct cni_opt_result **result);
+int version_network_plane(const struct cni_network_list_conf *list,
+ struct cni_version_info_list **result_version_list);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c
index c4bc81c0..4908565e 100644
--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c
+++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c
@@ -28,7 +28,7 @@
#include <sys/wait.h>
#include <isula_libutils/cni_inner_plugin_info.h>
-#include <isula_libutils/cni_version.h>
+#include <isula_libutils/cni_version_info.h>
#include <isula_libutils/log.h>
#include <isula_libutils/cni_exec_error.h>
#include <isula_libutils/auto_cleanup.h>
@@ -183,10 +183,10 @@ static char *str_cni_exec_error(const cni_exec_error *e_err)
static char *cniversion_decode(const char *jsonstr)
{
__isula_auto_free parser_error err = NULL;
- cni_version *conf = NULL;
+ cni_version_info *conf = NULL;
char *result = NULL;
- conf = cni_version_parse_data(jsonstr, NULL, &err);
+ conf = cni_version_info_parse_data(jsonstr, NULL, &err);
if (conf == NULL) {
ERROR("decoding config \"%s\", failed: %s", jsonstr, err);
goto out;
@@ -198,7 +198,7 @@ static char *cniversion_decode(const char *jsonstr)
result = util_strdup_s(conf->cni_version);
out:
- free_cni_version(conf);
+ free_cni_version_info(conf);
return result;
}
@@ -466,6 +466,84 @@ out:
return ret;
}
+static char *get_default_version_stdin(void)
+{
+ char *stdin_str = NULL;
+ int ret;
+
+ ret = asprintf(&stdin_str, "{\"cniVersion\":\"%s\"}", CURRENT_VERSION);
+ if (ret < 0) {
+ ERROR("parse cni version failed");
+ }
+ return stdin_str;
+}
+
+static int do_parse_version_info_stdout_str(int exec_ret, const cni_exec_error *e_err,
+ const char *stdout_str, cni_version_info **result_version)
+{
+ __isula_auto_free char *err_msg = NULL;
+ struct parser_context ctx = { OPT_GEN_SIMPLIFY, 0 };
+ __isula_auto_free parser_error perr = NULL;
+
+ if (exec_ret != 0) {
+ err_msg = str_cni_exec_error(e_err);
+ ERROR("raw exec failed: %s", err_msg);
+ isulad_append_error_message("raw exec failed: %s. ", err_msg);
+ return -1;
+ }
+
+ if (stdout_str == NULL || strlen(stdout_str) == 0) {
+ ERROR("Get empty version result");
+ return -1;
+ }
+ free_cni_version_info(*result_version);
+ *result_version = cni_version_info_parse_data(stdout_str, &ctx, &perr);
+ if (*result_version == NULL) {
+ ERROR("parse cni result version failed: %s", perr);
+ return -1;
+ }
+
+ return 0;
+}
+
+int get_version_info(const char *plugin_path, cni_version_info **result_version)
+{
+ __isula_auto_free char *err_msg = NULL;
+ char **envs = NULL;
+ __isula_auto_free char *stdout_str = NULL;
+ __isula_auto_free char *stdin_str = NULL;
+ cni_exec_error *e_err = NULL;
+ int ret = 0;
+ const struct cni_args cniargs = {
+ .command = "VERSION",
+ .netns = "dummy",
+ .ifname = "dummy",
+ .path = "dummy",
+ .container_id = "dummy"
+ };
+
+ stdin_str = get_default_version_stdin();
+ if (stdin_str == NULL) {
+ return -1;
+ }
+
+ envs = as_env(&cniargs);
+ if (envs == NULL) {
+ ERROR("create env failed");
+ return -1;
+ }
+
+ ret = raw_exec(plugin_path, stdin_str, envs, &stdout_str, &e_err);
+ DEBUG("Raw exec \"%s\" result: %d", plugin_path, ret);
+ DEBUG("Raw exec stdout: %s", stdout_str);
+ ret = do_parse_version_info_stdout_str(ret, e_err, stdout_str, result_version);
+
+ util_free_array(envs);
+ free_cni_exec_error(e_err);
+ return ret;
+
+}
+
void free_cni_args(struct cni_args *cargs)
{
size_t i = 0;
diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h
index 60b1c972..48d8d8b6 100644
--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h
+++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h
@@ -40,6 +40,8 @@ int exec_plugin_with_result(const char *plugin_path, const char *cni_net_conf_js
int exec_plugin_without_result(const char *plugin_path, const char *cni_net_conf_json, const struct cni_args *cniargs);
+int get_version_info(const char *plugin_path, cni_version_info **result_version);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c
index 164b2e29..aa4f75cf 100644
--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c
+++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c
@@ -741,3 +741,32 @@ struct cni_opt_result *new_result(const char *version, const char *jsonstr)
ERROR("unsupported CNI result version \"%s\"", version);
return NULL;
}
+
+size_t get_curr_support_version_len(void)
+{
+ return CURR_SUPPORT_VERSION_LEN;
+}
+
+int get_support_version_pos(const char *version)
+{
+ int i = 0;
+ if (version == NULL) {
+ return -1;
+ }
+
+ for (i = CURR_SUPPORT_VERSION_LEN - 1; i >= 0; i--) {
+ if ((g_curr_support_versions[i] != NULL) && (strcmp(version, g_curr_support_versions[i]) == 0)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+const char *get_support_version_by_pos(size_t pos)
+{
+ if (pos >= CURR_SUPPORT_VERSION_LEN) {
+ return NULL;
+ }
+ return g_curr_support_versions[pos];
+}
\ No newline at end of file
diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h
index 547bc915..438e1332 100644
--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h
+++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h
@@ -37,6 +37,12 @@ cni_result_curr *cni_result_curr_to_json_result(const struct cni_opt_result *src
struct cni_opt_result *copy_result_from_current(const cni_result_curr *curr_result);
+size_t get_curr_support_version_len(void);
+
+int get_support_version_pos(const char *version);
+
+const char *get_support_version_by_pos(size_t pos);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_api.c b/src/daemon/modules/network/cni_operator/libcni/libcni_api.c
index 781759e8..7f62df78 100644
--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.c
+++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.c
@@ -843,6 +843,112 @@ free_out:
return ret;
}
+static int version_network(const char *plugin_name, cni_version_info **result_version)
+{
+ int ret = 0;
+ __isula_auto_free char *plugin_path = NULL;
+
+ if (plugin_name == NULL) {
+ ERROR("Empty plugin name");
+ return -1;
+ }
+
+ ret = find_plugin_in_path(plugin_name, (const char * const *)g_module_conf.bin_paths,
+ g_module_conf.bin_paths_len, &plugin_path);
+ if (ret != 0) {
+ ERROR("Failed to find plugin: \"%s\"", plugin_name);
+ isulad_append_error_message("Failed to find plugin: \"%s\". ", plugin_name);
+ return ret;
+ }
+
+ // cni plugin calls should not take longer than 90 seconds
+ CALL_CHECK_TIMEOUT(90, ret = get_version_info(plugin_path, result_version));
+ return ret;
+}
+
+int cni_version_network_list(const struct cni_network_list_conf *list,
+ struct cni_version_info_list **result_version_list)
+{
+ int ret = 0;
+ int i;
+ cni_version_info *tmp_result_version = NULL;
+
+ if ((list == NULL) || (list->list == NULL) || (result_version_list == NULL)) {
+ ERROR("Empty arguments");
+ return -1;
+ }
+
+ *result_version_list = util_common_calloc_s(sizeof(struct cni_version_info_list));
+ if (*result_version_list == NULL) {
+ ERROR("Out of memory");
+ return -1;
+ }
+ (*result_version_list)->result_versions = util_smart_calloc_s(sizeof(cni_version_info *), list->list->plugins_len);
+ if ((*result_version_list)->result_versions == NULL) {
+ ERROR("Out of memory");
+ ret = -1;
+ goto free_out;
+ }
+
+ for (i = 0; i < list->list->plugins_len; i++) {
+ if (version_network(list->list->plugins[i]->type, &tmp_result_version) != 0) {
+ ret = -1;
+ ERROR("Run version plugin: %d failed", i);
+ goto free_out;
+ }
+ (*result_version_list)->result_versions[i] = tmp_result_version;
+ (*result_version_list)->result_versions_len += 1;
+ tmp_result_version = NULL;
+ }
+
+ return ret;
+
+free_out:
+ free_cni_version_info_list(*result_version_list);
+ *result_version_list = NULL;
+ return ret;
+}
+
+/* get the latest CNI version supported by all plugins */
+char *cni_get_plugins_supported_version(cni_net_conf_list *list)
+{
+ // init to default version, if no found, just return default version
+ char *cni_version = util_strdup_s(CURRENT_VERSION);
+ int i, j, version_pos;
+ struct cni_version_info_list *result_version_list = NULL;
+ struct cni_network_list_conf network_list = {
+ .list = list,
+ };
+ size_t curr_support_version_len = get_curr_support_version_len();
+ __isula_auto_free size_t *plugin_version_count = util_smart_calloc_s(sizeof(size_t), curr_support_version_len);
+ if (plugin_version_count == NULL) {
+ return cni_version;
+ }
+ if (cni_version_network_list(&network_list, &result_version_list) != 0) {
+ return cni_version;
+ }
+
+ // count plugin supported version
+ for (i = 0; i < result_version_list->result_versions_len; i++) {
+ for (j = result_version_list->result_versions[i]->supported_versions_len - 1; j >= 0 ; j--) {
+ version_pos = get_support_version_pos(result_version_list->result_versions[i]->supported_versions[j]);
+ if (version_pos < 0) {
+ break;
+ }
+ plugin_version_count[version_pos]++;
+ if (plugin_version_count[version_pos] == list->plugins_len) {
+ free(cni_version);
+ cni_version = util_strdup_s(get_support_version_by_pos(version_pos));
+ goto free_out;
+ }
+ }
+ }
+
+free_out:
+ free_cni_version_info_list(result_version_list);
+ return cni_version;
+}
+
static int do_copy_plugin_args(const struct runtime_conf *rc, struct cni_args **cargs)
{
size_t i = 0;
diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_api.h b/src/daemon/modules/network/cni_operator/libcni/libcni_api.h
index 878cb1bb..f94ab3f7 100644
--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.h
+++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.h
@@ -28,9 +28,6 @@
extern "C" {
#endif
-#define CURRENT_VERSION "1.0.0"
-#define SUPPORT_CACHE_AND_CHECK_VERSION "0.4.0"
-
#define SUPPORT_CAPABILITY_PORTMAPPINGS "portMappings"
#define SUPPORT_CAPABILITY_BANDWIDTH "bandwidth"
#define SUPPORT_CAPABILITY_IPRANGES "ipRanges"
@@ -87,6 +84,11 @@ int cni_del_network_list(const struct cni_network_list_conf *list, const struct
int cni_check_network_list(const struct cni_network_list_conf *list, const struct runtime_conf *rc,
struct cni_opt_result **p_result);
+
+int cni_version_network_list(const struct cni_network_list_conf *list,
+ struct cni_version_info_list **result_version_list);
+
+char *cni_get_plugins_supported_version(cni_net_conf_list *list);
void free_cni_port_mapping(struct cni_port_mapping *val);
diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c
index fd1091de..8a0ce1dd 100644
--- a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c
+++ b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c
@@ -129,3 +129,21 @@ void free_cni_opt_result(struct cni_opt_result *val)
val->my_dns = NULL;
free(val);
}
+
+void free_cni_version_info_list(struct cni_version_info_list *val)
+{
+ size_t i = 0;
+
+ if (val == NULL) {
+ return;
+ }
+
+ for (i = 0; i < val->result_versions_len; i++) {
+ free_cni_version_info(val->result_versions[i]);
+ val->result_versions[i] = NULL;
+ }
+ free(val->result_versions);
+ val->result_versions = NULL;
+
+ free(val);
+}
diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h
index abbc22fe..36640e63 100644
--- a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h
+++ b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h
@@ -19,10 +19,15 @@
#include <sys/types.h>
#include <stdbool.h>
+#include <isula_libutils/cni_version_info.h>
+
#ifdef __cplusplus
extern "C" {
#endif
+#define CURRENT_VERSION "1.0.0"
+#define SUPPORT_CACHE_AND_CHECK_VERSION "0.4.0"
+
/* define types for version */
struct cni_opt_result_interface {
char *name;
@@ -73,6 +78,11 @@ struct cni_opt_result {
struct cni_opt_result_dns *my_dns;
};
+struct cni_version_info_list {
+ cni_version_info **result_versions;
+ size_t result_versions_len;
+};
+
void free_cni_opt_result_ipconfig(struct cni_opt_result_ipconfig *ipc);
void free_cni_opt_result_route(struct cni_opt_result_route *val);
@@ -83,6 +93,8 @@ void free_cni_opt_result_dns(struct cni_opt_result_dns *val);
void free_cni_opt_result(struct cni_opt_result *val);
+void free_cni_version_info_list(struct cni_version_info_list *val);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/daemon/modules/network/native/adaptor_native.c b/src/daemon/modules/network/native/adaptor_native.c
index 4c63dec1..45288d7e 100644
--- a/src/daemon/modules/network/native/adaptor_native.c
+++ b/src/daemon/modules/network/native/adaptor_native.c
@@ -26,6 +26,7 @@
#include "linked_list.h"
#include "isulad_config.h"
#include <isula_libutils/log.h>
+#include <isula_libutils/auto_cleanup.h>
#include "utils_network.h"
#include "network_tools.h"
#include "cni_operate.h"
@@ -1301,7 +1302,7 @@ static cni_net_conf_list *conf_bridge(const network_create_request *request, str
list->plugins_len++;
}
- list->cni_version = util_strdup_s(CURRENT_VERSION);
+ list->cni_version = cni_get_plugins_supported_version(list);
if (request->name != NULL) {
list->name = util_strdup_s(request->name);
} else {
--
2.42.0
|