Line data Source code
1 :
2 : #include <stdio.h>
3 : #include <string.h>
4 : #include <stdlib.h>
5 : #include <stdbool.h>
6 : #include <errno.h>
7 : #include <unistd.h>
8 :
9 : #include <libxml/xmlmemory.h>
10 : #include <libxml/parser.h>
11 :
12 : #include <vtest.h>
13 : #include <vt_main.h>
14 : #include <vt_message.h>
15 : #include <vt_process_xml.h>
16 :
17 : #include <net/if.h>
18 : #include <nl_util.h>
19 :
20 : #include <vt_packet.h>
21 :
22 : extern struct vtest_module vt_modules[];
23 : #define SKIP_TEST_PFX "SKIP"
24 :
25 : int
26 2920 : vt_test_name(xmlNodePtr node, struct vtest *test)
27 : {
28 : xmlNodePtr child;
29 2920 : if (!node ||!test) {
30 0 : return E_PROCESS_XML_ERR_FARG;
31 : }
32 :
33 2920 : child = node->xmlChildrenNode;
34 2920 : if (!child || !child->content || !strlen(child->content)) {
35 0 : return E_MAIN_ERR_FARG;
36 : }
37 :
38 2920 : if (strncmp(child->content, SKIP_TEST_PFX,
39 : sizeof(SKIP_TEST_PFX) - 1) == 0) {
40 0 : printf("Skipping %s...\n", (char *)child->content +
41 : sizeof(SKIP_TEST_PFX) + 1);
42 0 : return E_MAIN_SKIP;
43 : } else {
44 2920 : printf("Running %s...\n", (char *)child->content);
45 : }
46 :
47 2920 : return E_PROCESS_XML_OK;
48 : }
49 :
50 : static int
51 0 : vt_search_vt_modules_by_name(char *vt_name) {
52 :
53 : // -1 = not found
54 0 : int ret = -1;
55 0 : size_t i = 0;
56 0 : if (!vt_name) {
57 0 : return -2;
58 : }
59 :
60 0 : for (i = 0; i < VTEST_NUM_MODULES; i++) {
61 0 : if (!strncmp(vt_name, vt_modules[i].vt_name,
62 0 : strlen(vt_modules[i].vt_name) + 1)) {
63 0 : return i;
64 : }
65 : }
66 0 : return ret;
67 : }
68 :
69 : static int
70 2794 : vt_check_return_val(struct vtest *test) {
71 :
72 : bool has_returned;
73 2794 : int xml_return_val = 0;
74 2794 : int returned_msg_val = 0;
75 :
76 2794 : if (!test || !test->messages.return_vrouter_msg) {
77 0 : return E_PROCESS_XML_ERR_FARG;
78 : }
79 :
80 2794 : has_returned = test->messages.return_vrouter_msg->has_returned;
81 2794 : xml_return_val = test->messages.data[test->message_ptr_num].xml_data.return_value;
82 2794 : returned_msg_val = test->messages.return_vrouter_msg->return_val[test->messages.return_vrouter_msg->ptr_num];
83 :
84 2794 : if (has_returned && xml_return_val == returned_msg_val) {
85 2384 : return E_PROCESS_XML_OK;
86 : }
87 :
88 410 : test->vtest_return = E_MAIN_TEST_FAIL;
89 :
90 410 : return E_PROCESS_XML_ERR;
91 : }
92 :
93 : static int
94 2794 : vt_send_vRouter_msg(struct vtest *test) {
95 :
96 5588 : return (vr_sendmsg(test->vrouter_cl, test->messages.data[test->message_ptr_num].mem,
97 2794 : test->messages.data[test->message_ptr_num].type));
98 : }
99 :
100 : static int
101 2794 : vt_recv_vRouter_msg( struct vtest *test) {
102 :
103 2794 : int ret = 0;
104 2794 : if (!test) {
105 0 : return E_PROCESS_XML_ERR_FARG;
106 : }
107 2794 : test->messages.return_vrouter_msg->has_returned = false;
108 2794 : ret = vr_recvmsg(test->vrouter_cl, false);
109 2794 : test->messages.data[test->message_ptr_num].recv_ret_value = ret;
110 2794 : return ret;
111 : }
112 :
113 : static int inline
114 2384 : vt_post_process_message_expect(struct vtest *test) {
115 :
116 2384 : if (test->messages.data[test->message_ptr_num].xml_data.is_element_expect) {
117 0 : vt_expect_node((xmlNodePtr)test->messages.data[test->message_ptr_num].xml_data.element_expect_ptr, test);
118 0 : if (test->messages.data[test->message_ptr_num].return_from_expected != true) {
119 0 : fprintf(stderr, "Message has different value then expected value.\n");
120 0 : test->vtest_return = E_MAIN_TEST_FAIL;
121 0 : return E_MAIN_ERR;
122 : }
123 : }
124 2384 : return E_PROCESS_XML_OK;
125 :
126 : }
127 :
128 : static void
129 2384 : vt_post_process_write_response_xml(struct vtest *test)
130 : {
131 2384 : sandesh_info_t *sinfo = NULL;
132 2384 : char* node_name = NULL;
133 2384 : int resp_index = test->messages.received_vrouter_msg->ptr_num;
134 2384 : int err = 0;
135 : ThriftXMLProtocol xml_proto;
136 : ThriftFileTransport file_transport;
137 :
138 2384 : if ((test->cli_opt.resp_file[0] == '\0') || (resp_index < 0)) {
139 1698 : return;
140 : }
141 :
142 686 : node_name = test->messages.data[test->message_ptr_num].type;
143 686 : if (!strncmp(node_name, "vr_flow_req", sizeof("vr_flow_req")))
144 206 : node_name = "vr_flow_response";
145 686 : sinfo = vr_find_sandesh_info(node_name);
146 686 : if (!sinfo) {
147 0 : fprintf(stderr, "Failed to find sandesh info for %s\n",
148 0 : test->messages.data[test->message_ptr_num].type);
149 0 : return;
150 : }
151 :
152 686 : fprintf(stdout, "Found sandesh info for %s\n",
153 686 : test->messages.data[test->message_ptr_num].type);
154 :
155 686 : fprintf(stdout, "Write response to xml file %s\n", test->cli_opt.resp_file);
156 686 : if (thrift_file_transport_init(&file_transport,
157 686 : test->cli_opt.resp_file) < 0) {
158 0 : fprintf(stderr, "Failed to open file %s\n", test->cli_opt.resp_file);
159 0 : return;
160 : }
161 686 : thrift_protocol_init((ThriftProtocol *)&xml_proto, T_PROTOCOL_XML,
162 : (ThriftTransport *)&file_transport);
163 686 : sinfo->write((void *)test->messages.received_vrouter_msg->\
164 : mem_handles[resp_index].mem, (ThriftProtocol *)&xml_proto, &err);
165 686 : if (err != 0) {
166 0 : fprintf(stderr, "Sandesh write returned error %d\n", err);
167 : }
168 686 : thrift_file_transport_close(&file_transport);
169 : }
170 :
171 : static int inline
172 2794 : vt_post_process_message(struct vtest *test) {
173 :
174 2794 : int ret = 0;
175 2794 : int tot_cnt = 0;
176 :
177 2794 : test->vtest_return = E_MAIN_TEST_PASS;
178 2794 : tot_cnt = test->message_ptr_num - test->message_ptr_start;
179 : /* reset the current pointer */
180 2794 : test->message_ptr_num = test->message_ptr_start;
181 : /*advance the start pointer */
182 2794 : test->message_ptr_start += tot_cnt;
183 2794 : tot_cnt++;
184 :
185 5178 : while (tot_cnt != 0) {
186 2794 : if (test->messages.data[test->message_ptr_num].mem) {
187 2794 : ret = vt_send_vRouter_msg(test);
188 2794 : if (!(ret > 0)) {
189 0 : fprintf(stderr, "Send message, failed\n");
190 0 : return E_PROCESS_XML_ERR_MSG_SEND;
191 : }
192 :
193 2794 : ret = vt_recv_vRouter_msg(test);
194 2794 : if (!(ret > 0)) {
195 0 : fprintf(stderr, "Receive message, failed\n");
196 0 : return E_PROCESS_XML_ERR_MSG_RECV;
197 : }
198 :
199 2794 : ret = vt_check_return_val(test);
200 2794 : if (ret != E_PROCESS_XML_OK) {
201 410 : fprintf(stderr, "Message has different return value, failed\n");
202 410 : return E_PROCESS_XML_ERR;
203 : }
204 :
205 : /* If expect element is in <message> file. */
206 2384 : ret = vt_post_process_message_expect(test);
207 2384 : if (ret != E_PROCESS_XML_OK) {
208 0 : fprintf(stderr, "Expected message has different value then returned, failed\n");
209 :
210 0 : return ret;
211 : }
212 : /* Write the response in XML file */
213 2384 : vt_post_process_write_response_xml(test);
214 : }
215 2384 : tot_cnt--;
216 2384 : test->message_ptr_num++;
217 : }
218 :
219 2384 : test->message_ptr_num = test->message_ptr_start;
220 2384 : return E_MAIN_OK;
221 : }
222 :
223 : static int inline
224 126 : vt_post_process_packet(struct vtest *test) {
225 :
226 126 : int ret = 0;
227 :
228 126 : ret = run_pcap_test(test);
229 126 : if (ret == EXIT_FAILURE) {
230 0 : test->vtest_return = E_MAIN_TEST_FAIL;
231 0 : return E_PROCESS_XML_ERR;
232 126 : } else if (ret == EXIT_SUCCESS) {
233 126 : test->vtest_return = E_MAIN_TEST_PASS;
234 126 : return E_PROCESS_XML_OK;
235 : }
236 :
237 0 : return E_PROCESS_XML_OK;
238 : }
239 :
240 : static int
241 5840 : vt_post_process_node(xmlNodePtr node, struct vtest *test) {
242 :
243 5840 : int ret = 0;
244 :
245 5840 : if (!test || !node) {
246 0 : return E_PROCESS_XML_ERR_FARG;
247 : }
248 :
249 5840 : if (!strncmp((char *) node->name, "message", sizeof("message"))) {
250 2794 : ret = vt_post_process_message(test);
251 :
252 : }
253 :
254 5840 : if(!strncmp((char *) node->name, "packet", sizeof("packet"))) {
255 126 : ret = vt_post_process_packet(test);
256 : }
257 :
258 5840 : return ret;
259 : }
260 :
261 : static int
262 5840 : vt_process_node(xmlNodePtr node, struct vtest *test)
263 : {
264 : unsigned int i;
265 5840 : int ret = 0;
266 :
267 5840 : if (!node || !test) {
268 0 : return E_PROCESS_XML_ERR_FARG;
269 : }
270 :
271 : /* control block is processed already */
272 5840 : if (!strncmp((char *) node->name, "control", sizeof("control"))) {
273 0 : return E_PROCESS_XML_OK;
274 : }
275 8886 : for (i = 0; i < VTEST_NUM_MODULES; i++) {
276 8886 : if (!strncmp((char *)node->name, vt_modules[i].vt_name,
277 8886 : strlen(vt_modules[i].vt_name) + 1)) {
278 5840 : ret = vt_modules[i].vt_node(node, test);
279 :
280 5840 : if (ret == E_MAIN_SKIP)
281 0 : return ret;
282 :
283 5840 : if (ret != E_MESSAGE_OK) {
284 0 : fprintf(stderr, "%s(): Error processing node %s\n",
285 : __func__, node->name);
286 0 : return ret;
287 : }
288 :
289 5840 : ret = vt_post_process_node(node, test);
290 5840 : if (ret != E_PROCESS_XML_OK) {
291 410 : fprintf(stderr, "%s(): Error post-processing node %s\n",
292 : __func__, node->name);
293 410 : return ret;
294 : }
295 :
296 5430 : return E_PROCESS_XML_OK;
297 : }
298 : }
299 :
300 0 : if (i == VTEST_NUM_MODULES) {
301 0 : fprintf(stderr, "Unrecognized node %s in XML\n", node->name);
302 0 : return E_PROCESS_XML_ERR;
303 : }
304 :
305 0 : return E_PROCESS_XML_ERR;
306 : }
307 :
308 : static int
309 2920 : vt_tree_traverse(xmlNodePtr node, struct vtest *test)
310 : {
311 2920 : int ret = 0;
312 :
313 2920 : if (!node || !test) {
314 0 : return E_PROCESS_XML_ERR_FARG;
315 : }
316 :
317 16700 : while (node) {
318 14190 : if (node->type == XML_ELEMENT_NODE) {
319 5840 : ret = vt_process_node(node, test);
320 5840 : if (ret == E_MAIN_SKIP) {
321 0 : return ret;
322 : }
323 :
324 5840 : if (ret != E_PROCESS_XML_OK) {
325 410 : fprintf(stderr ,"%s(): Tree traverse error %d\n",
326 : __func__, ret);
327 :
328 410 : return ret;
329 : }
330 : else {
331 5430 : test->vtest_break = 0;
332 : }
333 : }
334 13780 : node = node->next;
335 : }
336 :
337 2510 : return E_PROCESS_XML_ERR;
338 : }
339 :
340 : static int
341 2920 : vt_traverse_control_node(xmlNodePtr node, struct vtest *test)
342 : {
343 2920 : int ret = E_MAIN_SKIP;
344 :
345 2920 : if (!node || !test) {
346 0 : return E_PROCESS_XML_ERR_FARG;
347 : }
348 :
349 17520 : while (node) {
350 14600 : if (node->type == XML_ELEMENT_NODE) {
351 5840 : if (!strncmp((char *) node->name, "control", sizeof("control"))) {
352 0 : xmlNodePtr child_node = node->xmlChildrenNode;
353 0 : while (child_node) {
354 0 : if (!strncmp((char *) child_node->name, "flow_count",
355 : sizeof("flow_count"))) {
356 0 : if (child_node->children &&
357 0 : child_node->children->content) {
358 0 : test->flow_count =
359 0 : strtoul(child_node->children->content, NULL, 0);
360 0 : ret = E_MAIN_OK;
361 : }
362 : }
363 0 : child_node = child_node->next;
364 : }
365 : }
366 :
367 :
368 : }
369 14600 : node = node->next;
370 : }
371 2920 : return ret;
372 : }
373 :
374 : int
375 2920 : vt_parse_file(char *file, struct vtest *test)
376 : {
377 2920 : xmlDocPtr doc = NULL;
378 2920 : xmlNodePtr node = NULL;
379 : int ret;
380 :
381 :
382 2920 : doc = xmlParseFile(file);
383 2920 : if (!doc) {
384 0 : fprintf(stderr ,"%s(): Error parsing XML file %s\n", __func__, file);
385 0 : return E_PROCESS_XML_ERR;
386 : }
387 2920 : test->file_name = file;
388 :
389 2920 : node = xmlDocGetRootElement(doc);
390 2920 : if (!node) {
391 0 : fprintf(stderr ,"%s(): Error getting root element\n", __func__);
392 0 : return E_PROCESS_XML_ERR;
393 : }
394 :
395 2920 : ret = vt_traverse_control_node(node->xmlChildrenNode, test);
396 2920 : ret = vt_tree_traverse(node->xmlChildrenNode, test);
397 :
398 2920 : xmlFreeDoc(doc);
399 :
400 2920 : return ret;
401 : }
|