Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #ifndef _PROCESS_H_
6 : : #define _PROCESS_H_
7 : :
8 : : #include <errno.h> /* errno */
9 : : #include <limits.h> /* PATH_MAX */
10 : : #ifndef RTE_EXEC_ENV_WINDOWS
11 : : #include <sys/wait.h>
12 : : #endif
13 : : #include <stdlib.h> /* NULL */
14 : : #include <string.h> /* strerror */
15 : : #include <unistd.h>
16 : : #include <dirent.h>
17 : :
18 : : #include <rte_string_fns.h> /* strlcpy */
19 : : #include <rte_devargs.h>
20 : : #include <rte_eal.h>
21 : :
22 : : #ifdef RTE_LIB_PDUMP
23 : : #ifdef RTE_NET_RING
24 : : #include <rte_thread.h>
25 : : extern uint32_t send_pkts(void *empty);
26 : : extern uint16_t flag_for_send_pkts;
27 : : #endif
28 : : #endif
29 : :
30 : : #define PREFIX_ALLOW "--allow="
31 : : #define PREFIX_DRIVER_PATH "--driver-path="
32 : :
33 : : static int
34 : 0 : add_parameter_allow(char **argv, int max_capacity)
35 : : {
36 : : struct rte_devargs *devargs;
37 : : int count = 0;
38 : :
39 [ # # ]: 0 : RTE_EAL_DEVARGS_FOREACH(NULL, devargs) {
40 [ # # ]: 0 : if (strlen(devargs->name) == 0)
41 : 0 : continue;
42 : :
43 [ # # # # ]: 0 : if (devargs->data == NULL || strlen(devargs->data) == 0) {
44 [ # # ]: 0 : if (asprintf(&argv[count], PREFIX_ALLOW"%s", devargs->name) < 0)
45 : : break;
46 : : } else {
47 [ # # ]: 0 : if (asprintf(&argv[count], PREFIX_ALLOW"%s,%s",
48 : 0 : devargs->name, devargs->data) < 0)
49 : : break;
50 : : }
51 : :
52 [ # # ]: 0 : if (++count == max_capacity)
53 : : break;
54 : : }
55 : :
56 : 0 : return count;
57 : : }
58 : :
59 : : static int
60 : 0 : add_parameter_driver_path(char **argv, int max_capacity)
61 : : {
62 : : const char *driver_path;
63 : : int count = 0;
64 : :
65 [ # # ]: 0 : RTE_EAL_DRIVER_PATH_FOREACH(driver_path, true) {
66 [ # # ]: 0 : if (asprintf(&argv[count], PREFIX_DRIVER_PATH"%s", driver_path) < 0)
67 : : break;
68 : :
69 [ # # ]: 0 : if (++count == max_capacity)
70 : : break;
71 : : }
72 : :
73 : 0 : return count;
74 : : }
75 : :
76 : : /*
77 : : * launches a second copy of the test process using the given argv parameters,
78 : : * which should include argv[0] as the process name. To identify in the
79 : : * subprocess the source of the call, the env_value parameter is set in the
80 : : * environment as $RTE_TEST
81 : : */
82 : : static inline int
83 : 140 : process_dup(const char *const argv[], int numargs, const char *env_value)
84 : : {
85 : : int num = 0;
86 : : char **argv_cpy;
87 : : int allow_num;
88 : : int driver_path_num;
89 : : int argv_num;
90 : : int i, status;
91 : : #ifdef RTE_LIB_PDUMP
92 : : #ifdef RTE_NET_RING
93 : : rte_thread_t thread;
94 : : int rc;
95 : : #endif
96 : : #endif
97 : :
98 : 140 : pid_t pid = fork();
99 [ + - ]: 140 : if (pid < 0)
100 : : return -1;
101 [ - + ]: 140 : else if (pid == 0) {
102 : 0 : allow_num = rte_devargs_type_count(RTE_DEVTYPE_ALLOWED);
103 : 0 : driver_path_num = rte_eal_driver_path_count(true);
104 : 0 : argv_num = numargs + allow_num + driver_path_num + 1;
105 : 0 : argv_cpy = calloc(argv_num, sizeof(char *));
106 [ # # ]: 0 : if (!argv_cpy)
107 : 0 : rte_panic("Memory allocation failed\n");
108 : :
109 : : /* make a copy of the arguments to be passed to exec */
110 [ # # ]: 0 : for (i = 0; i < numargs; i++) {
111 : 0 : argv_cpy[i] = strdup(argv[i]);
112 [ # # ]: 0 : if (argv_cpy[i] == NULL)
113 : 0 : rte_panic("Error dup args\n");
114 : : }
115 [ # # ]: 0 : if (allow_num > 0)
116 : 0 : num = add_parameter_allow(&argv_cpy[i], allow_num);
117 : 0 : num += numargs;
118 : :
119 [ # # ]: 0 : if (driver_path_num > 0) {
120 : 0 : int added = add_parameter_driver_path(&argv_cpy[num], driver_path_num);
121 : 0 : num += added;
122 : : }
123 : :
124 : : #ifdef RTE_EXEC_ENV_LINUX
125 : : {
126 : : const char *procdir = "/proc/self/fd/";
127 : : struct dirent *dirent;
128 : : char *endptr;
129 : : int fd, fdir;
130 : : DIR *dir;
131 : :
132 : : /* close all open file descriptors, check /proc/self/fd
133 : : * to only call close on open fds. Exclude fds 0, 1 and
134 : : * 2
135 : : */
136 : 0 : dir = opendir(procdir);
137 [ # # ]: 0 : if (dir == NULL) {
138 : 0 : rte_panic("Error opening %s: %s\n", procdir,
139 : : strerror(errno));
140 : : }
141 : :
142 : 0 : fdir = dirfd(dir);
143 [ # # ]: 0 : if (fdir < 0) {
144 : 0 : status = errno;
145 : 0 : closedir(dir);
146 : 0 : rte_panic("Error %d obtaining fd for dir %s: %s\n",
147 : : fdir, procdir,
148 : : strerror(status));
149 : : }
150 : :
151 [ # # ]: 0 : while ((dirent = readdir(dir)) != NULL) {
152 : :
153 [ # # ]: 0 : if (strcmp(dirent->d_name, ".") == 0 ||
154 [ # # ]: 0 : strcmp(dirent->d_name, "..") == 0)
155 : 0 : continue;
156 : :
157 : 0 : errno = 0;
158 : 0 : fd = strtol(dirent->d_name, &endptr, 10);
159 [ # # # # ]: 0 : if (errno != 0 || endptr[0] != '\0') {
160 : : printf("Error converting name fd %d %s:\n",
161 : : fd, dirent->d_name);
162 : 0 : continue;
163 : : }
164 : :
165 [ # # ]: 0 : if (fd == fdir || fd <= 2)
166 : 0 : continue;
167 : :
168 : 0 : close(fd);
169 : : }
170 : 0 : closedir(dir);
171 : : }
172 : : #endif
173 : : printf("Running binary with argv[]:");
174 [ # # ]: 0 : for (i = 0; i < num; i++)
175 : 0 : printf("'%s' ", argv_cpy[i]);
176 : : printf("\n");
177 : 0 : fflush(stdout);
178 : :
179 : : /* set the environment variable */
180 [ # # ]: 0 : if (setenv(RECURSIVE_ENV_VAR, env_value, 1) != 0)
181 : 0 : rte_panic("Cannot export environment variable\n");
182 [ # # ]: 0 : if (execv(argv_cpy[0], argv_cpy) < 0)
183 : 0 : rte_panic("Cannot exec: %s\n", strerror(errno));
184 : : }
185 : : /* parent process does a wait */
186 : : #ifdef RTE_LIB_PDUMP
187 : : #ifdef RTE_NET_RING
188 [ + + ]: 140 : if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
189 : 1 : rc = rte_thread_create(&thread, NULL, send_pkts, NULL);
190 [ - + ]: 1 : if (rc != 0) {
191 : 0 : rte_panic("Cannot start send pkts thread: %s\n",
192 : : strerror(rc));
193 : : }
194 : : }
195 : : #endif
196 : : #endif
197 : :
198 [ - + ]: 140 : while (wait(&status) != pid)
199 : : ;
200 : : #ifdef RTE_LIB_PDUMP
201 : : #ifdef RTE_NET_RING
202 [ + + ]: 140 : if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
203 : 1 : flag_for_send_pkts = 0;
204 : 1 : rte_thread_join(thread, NULL);
205 : : }
206 : : #endif
207 : : #endif
208 : 140 : return status;
209 : : }
210 : :
211 : : /* Only Linux supports file prefixes. */
212 : : #ifndef RTE_EXEC_ENV_LINUX
213 : : static inline const char *
214 : : file_prefix_arg(void)
215 : : {
216 : : return "";
217 : : }
218 : : #else /* RTE_EXEC_ENV_LINUX */
219 : : static inline char *
220 : : get_current_prefix(char *prefix, int size)
221 : : {
222 : 12 : rte_basename(rte_eal_get_runtime_dir(), prefix, size);
223 : : return prefix;
224 : : }
225 : :
226 : : /* Return a --file-prefix=XXXX argument */
227 : : static inline const char *
228 : 11 : file_prefix_arg(void)
229 : : {
230 : : static char prefix[NAME_MAX + sizeof("--file-prefix=")];
231 : : char tmp[NAME_MAX];
232 : :
233 : : snprintf(prefix, sizeof(prefix), "--file-prefix=%s",
234 : : get_current_prefix(tmp, sizeof(tmp)));
235 : 11 : return prefix;
236 : : }
237 : : #endif /* RTE_EXEC_ENV_LINUX */
238 : :
239 : : #endif /* _PROCESS_H_ */
|