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