Line data Source code
1 : /*
2 : * vt_main.c -- test main function
3 : *
4 : * Copyright (c) 2015, Juniper Networks, Inc.
5 : * Copyright Contributors to the OpenSDN project
6 : * All rights reserved
7 : */
8 :
9 : #include <getopt.h>
10 : #include <stdio.h>
11 : #include <string.h>
12 : #include <stdlib.h>
13 : #include <stdbool.h>
14 : #include <errno.h>
15 : #include <unistd.h>
16 :
17 : #include <sys/types.h>
18 : #include <sys/stat.h>
19 :
20 : #include <libxml/xmlmemory.h>
21 : #include <libxml/parser.h>
22 :
23 : #include <vtest.h>
24 : #include <vt_main.h>
25 : #include <vt_message.h>
26 : #include <vt_process_xml.h>
27 :
28 : #include <vr_dpdk_usocket.h>
29 :
30 : #include <net/if.h>
31 : #include <nl_util.h>
32 : #include <vr_defs.h>
33 : #include <ini_parser.h>
34 :
35 : #include <vt_packet.h>
36 :
37 : /* vTest command-line options. */
38 : enum vr_opt_index {
39 : #define HELP_OPT "help"
40 : HELP_OPT_INDEX,
41 : #define VR_KMODE "vr_kmode"
42 : VR_KMODE_INDEX,
43 : #define SOCKET_DIR_OPT "vr_socket_dir"
44 : SOCKET_DIR_OPT_INDEX,
45 : #define NETLINK_PORT_OPT "vr_netlink_port"
46 : NETLINK_PORT_OPT_INDEX,
47 : #define SEND_SANDESH_REQ "send_sandesh_req"
48 : SEND_SANDESH_REQ_INDEX,
49 : #define RECV_SANDESH_RESP "recv_sandesh_resp"
50 : RECV_SANDESH_RESP_INDEX,
51 : #define SEND_RECV_PKT "send_recv_pkt"
52 : SEND_RECV_PKT_INDEX,
53 : MAX_OPT_INDEX
54 : };
55 :
56 : extern struct received_vrouter received_msg;
57 : extern struct return_vrouter return_msg;
58 :
59 : extern void vt_fill_nl_callbacks();
60 :
61 : struct vtest_module vt_modules[] = {
62 : { .vt_name = "test_name",
63 : .vt_node = vt_test_name,
64 : },
65 : {
66 : .vt_name = "message",
67 : .vt_node = vt_message,
68 : },
69 : {
70 : .vt_name = "packet",
71 : .vt_node = vt_packet,
72 : },
73 : };
74 :
75 : const size_t VTEST_NUM_MODULES = ARRAYSIZE(vt_modules);
76 :
77 : static void
78 2920 : vt_dealloc_test(struct vtest *test) {
79 2920 : int i = 0;
80 2920 : struct received_mem_handle *handles = test->messages.received_vrouter_msg->mem_handles;
81 :
82 2920 : vt_safe_free(test->vtest_name);
83 2920 : vt_safe_free(test->vtest_error_module);
84 :
85 5714 : for (i = 0; i <= test->message_ptr_num; ++i) {
86 2794 : vt_safe_free(test->messages.data[i].mem);
87 : }
88 :
89 :
90 3729 : for(i = 0; i <= test->messages.received_vrouter_msg->ptr_num; ++i) {
91 809 : handles[i].free_mem(handles[i].mem);
92 809 : vt_safe_free(handles[i].mem);
93 : }
94 :
95 2920 : return;
96 : }
97 :
98 : static int
99 2920 : vt_init(struct vtest *test)
100 : {
101 :
102 2920 : (test->messages).data = calloc(sizeof(struct message_element), VT_MESSAGES_MAX);
103 2920 : if(test->messages.data == NULL) {
104 0 : return E_MAIN_ERR_ALLOC;
105 : }
106 2920 : memset(&received_msg, 0, sizeof(received_msg));
107 2920 : memset(&return_msg, 0, sizeof(return_msg));
108 :
109 2920 : test->messages.received_vrouter_msg = &received_msg;
110 2920 : test->messages.return_vrouter_msg = &return_msg;
111 2920 : test->message_ptr_num = -1;
112 2920 : test->message_ptr_start = -1;
113 2920 : test->flow_count = 1;
114 :
115 2920 : received_msg.ptr_num = test->message_ptr_num;
116 2920 : return_msg.ptr_num = test->message_ptr_num;
117 :
118 2920 : test->vtest_name = calloc(VT_MAX_TEST_NAME_LEN, 1);
119 2920 : if (!test->vtest_name) {
120 0 : return E_MAIN_ERR_ALLOC;
121 : }
122 :
123 2920 : test->vtest_error_module = calloc(VT_MAX_TEST_MODULE_NAME_LEN, 1);
124 2920 : if (!test->vtest_error_module) {
125 0 : return E_MAIN_ERR_ALLOC;
126 : }
127 :
128 2920 : return E_MAIN_OK;
129 :
130 : }
131 :
132 : static void
133 0 : vt_Usage(void)
134 : {
135 0 : printf(
136 : "Usage: "VT_PROG_NAME" [options]\n"
137 : " <xml file> [deprecated]\n"
138 : " --"HELP_OPT" This help\n"
139 : "\n"
140 : " --"VR_KMODE" Enables interaction with the vrouter kernel module\n"
141 : " --"SEND_SANDESH_REQ" <xml file>\n"
142 : " --"RECV_SANDESH_RESP" <xml file>\n"
143 : " --"SEND_RECV_PKT" <xml file>\n"
144 : " --"SOCKET_DIR_OPT" DIR Socket directory to use\n"
145 : " --"NETLINK_PORT_OPT" PORT Netlink TCP port to use\n"
146 : );
147 :
148 0 : exit(1);
149 : }
150 :
151 : static void
152 6534 : parse_long_opts(int opt_flow_index, char *optarg, vtest_cli_opt_t *cli_opt)
153 : {
154 6534 : errno = 0;
155 :
156 6534 : switch (opt_flow_index) {
157 2920 : case SOCKET_DIR_OPT_INDEX:
158 2920 : vr_socket_dir = optarg;
159 2920 : break;
160 :
161 0 : case NETLINK_PORT_OPT_INDEX:
162 0 : vr_netlink_port = (unsigned int)strtoul(optarg, NULL, 0);
163 0 : if (errno != 0) {
164 0 : vr_netlink_port = VR_DEF_NETLINK_PORT;
165 : }
166 0 : break;
167 :
168 2794 : case SEND_SANDESH_REQ_INDEX:
169 2794 : if (strlen(optarg) >= VT_MAX_FILENAME) {
170 0 : printf("Filename size exceeded limit of 128\n");
171 : } else {
172 2794 : cli_opt->cli_cmd = VTEST_CLI_CMD_SANDESH_REQ;
173 2794 : strcpy(cli_opt->req_file, optarg);
174 : }
175 2794 : break;
176 694 : case RECV_SANDESH_RESP_INDEX:
177 694 : if (strlen(optarg) >= VT_MAX_FILENAME) {
178 0 : printf("Filename size exceeded limit of 128\n");
179 : } else {
180 694 : cli_opt->cli_cmd = VTEST_CLI_CMD_SANDESH_REQ;
181 694 : strcpy(cli_opt->resp_file, optarg);
182 : }
183 694 : break;
184 126 : case SEND_RECV_PKT_INDEX:
185 126 : if (strlen(optarg) >= VT_MAX_FILENAME) {
186 0 : printf("Filename size exceeded limit of 128\n");
187 : } else {
188 126 : cli_opt->cli_cmd = VTEST_CLI_CMD_PACKET_REQ;
189 126 : strcpy(cli_opt->req_file, optarg);
190 : }
191 126 : break;
192 0 : case VR_KMODE_INDEX:
193 0 : cli_opt->vr_kmode = true;
194 0 : break;
195 0 : case HELP_OPT_INDEX:
196 : default:
197 0 : vt_Usage();
198 : }
199 6534 : }
200 :
201 : static struct option long_options[] = {
202 : [HELP_OPT_INDEX] = {HELP_OPT, no_argument,
203 : NULL, 0},
204 : [VR_KMODE_INDEX] = {VR_KMODE, no_argument,
205 : NULL, 0},
206 : [SEND_SANDESH_REQ_INDEX] = {SEND_SANDESH_REQ, required_argument,
207 : NULL, 0},
208 : [RECV_SANDESH_RESP_INDEX] = {RECV_SANDESH_RESP, required_argument,
209 : NULL, 0},
210 : [SEND_RECV_PKT_INDEX] = {SEND_RECV_PKT, required_argument,
211 : NULL, 0},
212 : [SOCKET_DIR_OPT_INDEX] = {SOCKET_DIR_OPT, required_argument,
213 : NULL, 0},
214 : [NETLINK_PORT_OPT_INDEX] = {NETLINK_PORT_OPT, required_argument,
215 : NULL, 0},
216 : [MAX_OPT_INDEX] = {NULL, 0,
217 : NULL, 0},
218 : };
219 :
220 : int
221 2920 : main(int argc, char *argv[])
222 : {
223 : int ret, opt, option_index;
224 : unsigned int i;
225 :
226 : struct stat stat_buf;
227 : struct vtest vtest;
228 :
229 2920 : memset(&vtest, 0, sizeof(struct vtest));
230 :
231 2920 : vt_fill_nl_callbacks();
232 :
233 9454 : while ((opt = getopt_long(argc, argv, "", long_options, &option_index))
234 9454 : >= 0) {
235 6534 : switch (opt) {
236 6534 : case 0:
237 6534 : parse_long_opts(option_index, optarg, &vtest.cli_opt);
238 6534 : break;
239 :
240 0 : case '?':
241 : default:
242 0 : fprintf(stderr, "Invalid option %s\n", argv[optind - 1]);
243 0 : vt_Usage();
244 : }
245 : }
246 :
247 : /* Backward compatiblity stuff */
248 2920 : if ((vtest.cli_opt.cli_cmd != VTEST_CLI_CMD_SANDESH_REQ) &&
249 126 : (vtest.cli_opt.cli_cmd != VTEST_CLI_CMD_PACKET_REQ) &&
250 0 : (strcmp((argv[argc-1] + strlen(argv[argc-1]) - 3),
251 : "xml") == 0)) {
252 0 : vtest.cli_opt.cli_cmd = VTEST_CLI_CMD_SINGLE_TEST_FILE;
253 0 : strcpy(vtest.cli_opt.req_file, argv[argc-1]);
254 : }
255 :
256 2920 : ret = stat(vtest.cli_opt.req_file, &stat_buf);
257 2920 : if (ret) {
258 0 : fprintf(stderr, "%s: File not found: %s\n", __func__, vtest.cli_opt.req_file);
259 0 : return E_MAIN_ERR_XML;
260 : }
261 2920 : ret = vt_init(&vtest);
262 2920 : if (ret != E_MAIN_OK) {
263 0 : return ret;
264 : }
265 :
266 2920 : if (!vtest.cli_opt.vr_kmode) {
267 2920 : set_platform_vtest();
268 : }
269 2920 : vtest.vrouter_cl = vr_get_nl_client(VR_NETLINK_PROTO_DEFAULT);
270 2920 : if (!vtest.vrouter_cl) {
271 0 : fprintf(stderr, "Error registering NetLink client: %s (%d)\n",
272 0 : strerror(errno), errno);
273 0 : return E_MAIN_ERR_SOCK;
274 : }
275 :
276 11680 : for (i = 0; i < VTEST_NUM_MODULES; i++) {
277 8760 : if (vt_modules[i].vt_init) {
278 0 : ret = vt_modules[i].vt_init();
279 0 : if (ret != E_MAIN_OK) {
280 0 : fprintf(stderr, "%s: %s init failed\n", VT_PROG_NAME,
281 : vt_modules[i].vt_name);
282 0 : return E_MAIN_ERR;
283 : }
284 : }
285 : }
286 :
287 2920 : vt_parse_file(vtest.cli_opt.req_file, &vtest);
288 :
289 2920 : nl_free_client(vtest.vrouter_cl);
290 2920 : vt_dealloc_test(&vtest);
291 :
292 2920 : if (vtest.vtest_return == E_MAIN_TEST_FAIL) {
293 410 : return EXIT_FAILURE;//E_MAIN_TEST_FAIL;
294 :
295 2510 : } else if (vtest.vtest_return == E_MAIN_TEST_PASS) {
296 2510 : return EXIT_SUCCESS;//E_MAIN_TEST_PASS;
297 :
298 : } else {
299 0 : return 2;
300 : }
301 :
302 : return EXIT_SUCCESS;
303 : }
304 :
|