nat: Include platform specific headers on FreeBSD
[vpp.git] / src / plugins / nat / pnat / tests / pnat_test.c
1 /*
2  * Copyright (c) 2021 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <stdbool.h>
17 #include <assert.h>
18 #include <vlib/vlib.h>
19 #include <vnet/feature/feature.h>
20 #include <vppinfra/clib_error.h>
21 #include <vnet/ip/ip4_packet.h>
22 #include <vnet/udp/udp.h>
23 #include <vppinfra/bihash_16_8.h>
24 #include <vppinfra/bihash_template.c>
25 #include <vnet/fib/ip4_fib.h>
26 #include "../pnat.h"
27 #include <pnat/pnat.api_enum.h> /* For error counters */
28 #ifdef __FreeBSD__
29 #include <sys/socket.h>
30 #include <sys/types.h>
31 #include <netinet/in.h>
32 #endif /* __FreeBSD__ */
33 #include <arpa/inet.h>
34 #include "pnat_test_stubs.h"
35
36 /*
37 ** Buffer management in test setup
38 ** Allocate buffers return vector of buffer indicies.
39 **
40 ** Setup frame with buffers when calling function.
41 ** Global vector of all buffers with their indicies?
42 ** Convert buffer index to pointer?
43 */
44 struct buffers {
45     u8 data[2048];
46 };
47 struct buffers buffers[256];
48 struct buffers expected[256];
49 u32 *buffers_vector = 0;
50
51 static u32 *buffer_init(u32 *vector, int count) {
52     int i;
53     for (i = 0; i < count; i++) {
54         vec_add1(vector, i);
55     }
56     return vector;
57 }
58
59 u32 *results_bi = 0; /* global vector of result buffers */
60 u16 *results_next = 0;
61
62 vlib_node_runtime_t *node;
63
64 #define log_info(M, ...)                                                       \
65     fprintf(stderr, "\033[32;1m[OK] " M "\033[0m\n", ##__VA_ARGS__)
66 #define log_error(M, ...)                                                      \
67     fprintf(stderr, "\033[31;1m[ERROR] (%s:%d:) " M "\033[0m\n", __FILE__,     \
68             __LINE__, ##__VA_ARGS__)
69 #define test_assert_log(A, M, ...)                                             \
70     if (!(A)) {                                                                \
71         log_error(M, ##__VA_ARGS__);                                           \
72         assert(A);                                                             \
73     } else {                                                                   \
74         log_info(M, ##__VA_ARGS__);                                            \
75     }
76 #define test_assert(A, M, ...)                                                 \
77     if (!(A)) {                                                                \
78         log_error(M, ##__VA_ARGS__);                                           \
79         assert(A);                                                             \
80     }
81
82 /*
83  * Always return the frame of generated packets
84  */
85 #define vlib_frame_vector_args test_vlib_frame_vector_args
86 void *test_vlib_frame_vector_args(vlib_frame_t *f) { return buffers_vector; }
87
88 /* Synthetic value for vnet_feature_next  */
89 #define NEXT_PASSTHROUGH 4242
90
91 #define vnet_feature_next_u16 test_vnet_feature_next_u16
92 void vnet_feature_next_u16(u16 *next0, vlib_buffer_t *b0) {
93     *next0 = NEXT_PASSTHROUGH;
94 }
95
96 /* Gather output packets */
97 #define vlib_buffer_enqueue_to_next test_vlib_buffer_enqueue_to_next
98 void test_vlib_buffer_enqueue_to_next(vlib_main_t *vm,
99                                       vlib_node_runtime_t *node, u32 *buffers,
100                                       u16 *nexts, uword count) {
101     vec_add(results_next, nexts, count);
102     vec_add(results_bi, buffers, count);
103 }
104
105 pnat_trace_t trace = {0};
106 #define vlib_add_trace test_vlib_add_trace
107 void *test_vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r,
108                           vlib_buffer_t *b, u32 n_data_bytes) {
109     return &trace;
110 }
111
112 #define vlib_get_buffers test_vlib_get_buffers
113 void test_vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b,
114                            int count) {
115     int i;
116     for (i = 0; i < count; i++) {
117         b[i] = (vlib_buffer_t *)&buffers[bi[i]];
118     }
119 }
120
121 vlib_buffer_t *test_vlib_get_buffer(u32 bi) {
122     return (vlib_buffer_t *)&buffers[bi];
123 }
124
125 /* Must be included here to allow the above functions to override */
126 #include "../pnat_node.h"
127
128 /*** TESTS ***/
129
130 typedef struct {
131     char *name;
132     int nsend;
133     char *send;
134     int nexpect;
135     char *expect;
136     u32 expect_next_index;
137 } test_t;
138 #include "test_packets.h"
139
140 /* Rules */
141 typedef struct {
142     char *src;
143     char *dst;
144     u8 proto;
145     u16 sport;
146     u16 dport;
147     u8 from_offset;
148     u8 to_offset;
149     u8 clear_offset;
150 } test_5tuple_t;
151
152 typedef struct {
153     test_5tuple_t match;
154     test_5tuple_t rewrite;
155     bool in;
156     u32 index;
157 } rule_t;
158
159 rule_t rules[] = {
160     {
161         .match = {.dst = "2.2.2.2", .proto = 17, .dport = 6871},
162         .rewrite = {.dst = "1.2.3.4"},
163         .in = true,
164     },
165     {
166         .match = {.dst = "2.2.2.2", .proto = 6, .dport = 6871},
167         .rewrite = {.dst = "1.2.3.4"},
168         .in = true,
169     },
170     {
171         .match = {.dst = "2.2.2.2", .proto = 6, .dport = 6872},
172         .rewrite = {.dst = "1.2.3.4", .sport = 53, .dport = 8000},
173         .in = true,
174     },
175     {
176         .match = {.dst = "2.2.2.2", .proto = 6, .dport = 6873},
177         .rewrite = {.dst = "1.2.3.4", .sport = 53, .dport = 8000},
178         .in = true,
179     },
180     {
181         .match = {.dst = "2.2.2.2", .proto = 17, .dport = 6874},
182         .rewrite = {.from_offset = 15, .to_offset = 19},
183         .in = true,
184     },
185     {
186         .match = {.dst = "2.2.2.2", .proto = 17, .dport = 6875},
187         .rewrite = {.from_offset = 15, .to_offset = 50},
188         .in = true,
189     },
190     {
191         .match = {.dst = "2.2.2.2", .proto = 17, .dport = 6877},
192         .rewrite = {.dst = "1.2.3.4", .from_offset = 15, .to_offset = 35},
193         .in = true,
194     },
195     {
196         .match = {.dst = "2.2.2.2", .proto = 17, .dport = 6876},
197         .rewrite = {.clear_offset = 22},
198         .in = true,
199     },
200 };
201
202 static int fill_packets(vlib_main_t *vm, vlib_buffer_t *b, int n, char *test) {
203     b->flags |= VLIB_BUFFER_IS_TRACED;
204
205     ip4_header_t *ip = (ip4_header_t *)vlib_buffer_get_current(b);
206
207     memcpy(ip, test, n);
208
209     /* Do the work of SVR */
210     vnet_buffer(b)->ip.reass.l4_src_port = 0;
211     vnet_buffer(b)->ip.reass.l4_dst_port = 0;
212     b->current_length = n;
213
214     if (ip4_is_fragment(ip))
215         return 0;
216     if (ip->protocol == IP_PROTOCOL_UDP) {
217         udp_header_t *udp = ip4_next_header(ip);
218         vnet_buffer(b)->ip.reass.l4_src_port = udp->src_port;
219         vnet_buffer(b)->ip.reass.l4_dst_port = udp->dst_port;
220     } else if (ip->protocol == IP_PROTOCOL_TCP) {
221         tcp_header_t *tcp = ip4_next_header(ip);
222         vnet_buffer(b)->ip.reass.l4_src_port = tcp->src_port;
223         vnet_buffer(b)->ip.reass.l4_dst_port = tcp->dst_port;
224     }
225     return 0;
226 }
227
228 static void ruletomatch(test_5tuple_t *r, pnat_match_tuple_t *t) {
229     if (r->src) {
230         inet_pton(AF_INET, r->src, &t->src);
231         t->mask |= PNAT_SA;
232     }
233     if (r->dst) {
234         inet_pton(AF_INET, r->dst, &t->dst);
235         t->mask |= PNAT_DA;
236     }
237     if (r->dport) {
238         t->dport = r->dport;
239         t->mask |= PNAT_DPORT;
240     }
241     if (r->sport) {
242         t->sport = r->sport;
243         t->mask |= PNAT_SPORT;
244     }
245     t->proto = r->proto;
246 }
247
248 static void ruletorewrite(test_5tuple_t *r, pnat_rewrite_tuple_t *t) {
249     if (r->src) {
250         inet_pton(AF_INET, r->src, &t->src);
251         t->mask |= PNAT_SA;
252     }
253     if (r->dst) {
254         inet_pton(AF_INET, r->dst, &t->dst);
255         t->mask |= PNAT_DA;
256     }
257     if (r->dport) {
258         t->dport = r->dport;
259         t->mask |= PNAT_DPORT;
260     }
261     if (r->sport) {
262         t->sport = r->sport;
263         t->mask |= PNAT_SPORT;
264     }
265     if (r->to_offset || r->from_offset) {
266         t->to_offset = r->to_offset;
267         t->from_offset = r->from_offset;
268         t->mask |= PNAT_COPY_BYTE;
269     }
270     if (r->clear_offset) {
271         t->clear_offset = r->clear_offset;
272         t->mask |= PNAT_CLEAR_BYTE;
273     }
274 }
275
276 static void add_translation(rule_t *r) {
277     pnat_match_tuple_t match = {0};
278     pnat_rewrite_tuple_t rewrite = {0};
279
280     ruletomatch(&r->match, &match);
281     ruletorewrite(&r->rewrite, &rewrite);
282
283     int rv = pnat_binding_add(&match, &rewrite, &r->index);
284     assert(rv == 0);
285
286     rv = pnat_binding_attach(0, PNAT_IP4_INPUT, r->index);
287     assert(rv == 0);
288 }
289
290 static void del_translation(rule_t *r) {
291     int rv = pnat_binding_detach(0, PNAT_IP4_INPUT, r->index);
292     assert(rv == 0);
293
294     rv = pnat_binding_del(r->index);
295     assert(rv == 0);
296 }
297
298 static void validate_packet(vlib_main_t *vm, char *name, u32 bi,
299                             vlib_buffer_t *expected_b) {
300     vlib_buffer_t *b = test_vlib_get_buffer(bi);
301     assert(b);
302
303     ip4_header_t *ip = (ip4_header_t *)vlib_buffer_get_current(b);
304     ip4_header_t *expected_ip =
305         (ip4_header_t *)vlib_buffer_get_current(expected_b);
306
307     if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP) {
308         u32 flags = ip4_tcp_udp_validate_checksum(vm, b);
309         test_assert((flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0, "%s",
310                     name);
311         flags = ip4_tcp_udp_validate_checksum(vm, expected_b);
312         test_assert((flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0, "%s",
313                     name);
314     }
315     test_assert(b->current_length == expected_b->current_length, "%s %d vs %d",
316                 name, b->current_length, expected_b->current_length);
317
318     if (memcmp(ip, expected_ip, b->current_length) != 0) {
319         if (ip->protocol == IP_PROTOCOL_UDP) {
320             udp_header_t *udp = ip4_next_header(ip);
321             clib_warning("Received: IP: %U UDP: %U", format_ip4_header, ip,
322                          sizeof(*ip), format_udp_header, udp, sizeof(*udp));
323             udp = ip4_next_header(expected_ip);
324             clib_warning("%U", format_hexdump, ip, b->current_length);
325             clib_warning("Expected: IP: %U UDP: %U", format_ip4_header,
326                          expected_ip, sizeof(*ip), format_udp_header, udp,
327                          sizeof(*udp));
328             clib_warning("%U", format_hexdump, expected_ip,
329                          expected_b->current_length);
330         } else if (ip->protocol == IP_PROTOCOL_TCP) {
331             tcp_header_t *tcp = ip4_next_header(ip);
332             clib_warning("Received IP: %U TCP: %U", format_ip4_header, ip,
333                          sizeof(*ip), format_tcp_header, tcp, sizeof(*tcp));
334             tcp = ip4_next_header(expected_ip);
335             clib_warning("Expected IP: %U TCP: %U", format_ip4_header,
336                          expected_ip, sizeof(*ip), format_tcp_header, tcp,
337                          sizeof(*tcp));
338         } else {
339             clib_warning("Received: IP: %U", format_ip4_header, ip,
340                          sizeof(*ip));
341             clib_warning("Expected: IP: %U", format_ip4_header, expected_ip,
342                          sizeof(*ip));
343         }
344         test_assert_log(0, "%s", name);
345     } else {
346         test_assert_log(1, "%s", name);
347     }
348 }
349
350 extern vlib_node_registration_t pnat_input_node;
351
352 static void test_table(test_t *t, int no_tests) {
353     // walk through table of tests
354     int i;
355     vlib_main_init();
356     vlib_main_t *vm = vlib_get_first_main();
357
358     /* Generate packet data */
359     for (i = 0; i < no_tests; i++) {
360         // create input buffer(s)
361         fill_packets(vm, (vlib_buffer_t *)&buffers[i], t[i].nsend, t[i].send);
362         fill_packets(vm, (vlib_buffer_t *)&expected[i], t[i].nexpect,
363                      t[i].expect);
364     }
365
366     /* send packets through graph node */
367     vlib_frame_t frame = {.n_vectors = no_tests};
368     node->flags |= VLIB_NODE_FLAG_TRACE;
369
370     pnat_node_inline(vm, node, &frame, PNAT_IP4_INPUT, VLIB_RX);
371
372     /* verify tests */
373     for (i = 0; i < no_tests; i++) {
374         test_assert(t[i].expect_next_index == results_next[i], "%s", t[i].name);
375         validate_packet(vm, t[i].name, results_bi[i],
376                         (vlib_buffer_t *)&expected[i]);
377     }
378     vec_free(results_next);
379     vec_free(results_bi);
380 }
381
382 void test_performance(void) {
383     pnat_main_t *pm = &pnat_main;
384     int i;
385     vlib_main_t *vm = vlib_get_first_main();
386
387     for (i = 0; i < sizeof(rules) / sizeof(rules[0]); i++) {
388         add_translation(&rules[i]);
389     }
390     assert(pool_elts(pm->translations) == sizeof(rules) / sizeof(rules[0]));
391
392     int no_tests = sizeof(tests_packets) / sizeof(tests_packets[0]);
393     /* Generate packet data */
394     for (i = 0; i < VLIB_FRAME_SIZE; i++) {
395         // create input buffer(s)
396         fill_packets(vm, (vlib_buffer_t *)&buffers[i],
397                      tests_packets[i % no_tests].nsend,
398                      tests_packets[i % no_tests].send);
399         // fill_packets(vm, (vlib_buffer_t *)&expected[i], &tests[i %
400         // no_tests].expect);
401     }
402
403     /* send packets through graph node */
404     vlib_frame_t frame = {.n_vectors = VLIB_FRAME_SIZE};
405     node->flags &= ~VLIB_NODE_FLAG_TRACE;
406
407     int j;
408     for (j = 0; j < 10000; j++) {
409         pnat_node_inline(vm, node, &frame, PNAT_IP4_INPUT, VLIB_RX);
410
411 #if 0
412     for (i = 0; i < VLIB_FRAME_SIZE; i++) {
413         assert(tests[i % no_tests].expect_next_index == results_next[i]);
414         validate_packet(vm, tests[i % no_tests].name, results_bi[i], (vlib_buffer_t *)&expected[i]);
415     }
416 #endif
417         vec_free(results_next);
418         vec_free(results_bi);
419     }
420
421     for (i = 0; i < sizeof(rules) / sizeof(rules[0]); i++) {
422         del_translation(&rules[i]);
423     }
424     assert(pool_elts(pm->translations) == 0);
425     assert(pool_elts(pm->interfaces) == 0);
426 }
427
428 void test_packets(void) {
429     pnat_main_t *pm = &pnat_main;
430     int i;
431     for (i = 0; i < sizeof(rules) / sizeof(rules[0]); i++) {
432         add_translation(&rules[i]);
433     }
434     assert(pool_elts(pm->translations) == sizeof(rules) / sizeof(rules[0]));
435
436     test_table(tests_packets, sizeof(tests_packets) / sizeof(tests_packets[0]));
437
438     for (i = 0; i < sizeof(rules) / sizeof(rules[0]); i++) {
439         del_translation(&rules[i]);
440     }
441     assert(pool_elts(pm->translations) == 0);
442     assert(pool_elts(pm->interfaces) == 0);
443 }
444
445 static void test_attach(void) {
446     pnat_attachment_point_t attachment = PNAT_IP4_INPUT;
447     u32 binding_index = 0;
448     u32 sw_if_index = 0;
449     int rv = pnat_binding_attach(sw_if_index, attachment, binding_index);
450     test_assert(rv == -1, "binding_attach - nothing to attach");
451
452     rv = pnat_binding_detach(sw_if_index, attachment, 1234);
453     test_assert(rv == -1, "binding_detach - nothing to detach");
454
455     pnat_match_tuple_t match = {.mask = PNAT_SA};
456     pnat_rewrite_tuple_t rewrite = {.mask = PNAT_SA};
457     rv = pnat_binding_add(&match, &rewrite, &binding_index);
458     assert(rv == 0);
459
460     rv = pnat_binding_attach(sw_if_index, attachment, binding_index);
461     test_assert(rv == 0, "binding_attach - rule");
462
463     rv = pnat_binding_detach(sw_if_index, attachment, binding_index);
464     test_assert(rv == 0, "binding_detach - rule");
465
466     rv = pnat_binding_del(binding_index);
467     assert(rv == 0);
468 }
469
470 static void test_del_before_detach(void) {
471     pnat_attachment_point_t attachment = PNAT_IP4_INPUT;
472     u32 binding_index = 0;
473     u32 sw_if_index = 0;
474
475     /* Ensure 5-tuple here will not duplicate with other tests cause this will
476      * not be removed from flow cache */
477     rule_t rule = {
478         .match = {.dst = "123.123.123.123", .proto = 17, .dport = 6871},
479         .rewrite = {.dst = "1.2.3.4"},
480         .in = true,
481     };
482
483     add_translation(&rule);
484
485     int rv = pnat_binding_del(binding_index);
486     assert(rv == 0);
487
488     test_table(&tests_missing_rule[0], 1);
489
490     /* For now if you have deleted before detach, can't find key */
491     rv = pnat_binding_detach(sw_if_index, attachment, binding_index);
492     test_assert(rv == -1, "binding_detach - failure");
493
494     /* Re-add the rule and try again */
495     pnat_match_tuple_t match = {0};
496     pnat_rewrite_tuple_t rewrite = {0};
497     ruletomatch(&rule.match, &match);
498     ruletorewrite(&rule.rewrite, &rewrite);
499     rv = pnat_binding_add(&match, &rewrite, &binding_index);
500     assert(rv == 0);
501     rv = pnat_binding_detach(sw_if_index, attachment, binding_index);
502     test_assert(rv == 0, "binding_detach - pass");
503     rv = pnat_binding_del(binding_index);
504     assert(rv == 0);
505 }
506
507 void test_api(void) {
508     test_attach();
509     test_del_before_detach();
510 }
511
512 void test_checksum(void) {
513     int i;
514     vlib_main_t *vm = vlib_get_first_main();
515     pnat_main_t *pm = &pnat_main;
516
517     test_t test = {
518         .name = "checksum",
519         .nsend = 28,
520         .send =
521             (char[]){0x45, 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
522                      0x74, 0xcb, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
523                      0x00, 0x50, 0x1a, 0xd7, 0x00, 0x08, 0xde, 0xb1},
524     };
525
526     for (i = 0; i < sizeof(rules) / sizeof(rules[0]); i++) {
527         add_translation(&rules[i]);
528     }
529     assert(pool_elts(pm->translations) == sizeof(rules) / sizeof(rules[0]));
530
531     /* send packets through graph node */
532     vlib_frame_t frame = {.n_vectors = 1};
533     node->flags |= VLIB_NODE_FLAG_TRACE;
534
535     ip4_header_t *ip =
536         (ip4_header_t *)vlib_buffer_get_current((vlib_buffer_t *)&buffers[0]);
537
538     for (i = 0; i < 65535; i++) {
539
540         /* Get a buffer. Loop through 64K variations of it to check checksum */
541         memset(&buffers[0], 0, 2048);
542         fill_packets(vm, (vlib_buffer_t *)&buffers[0], test.nsend, test.send);
543
544         ip->src_address.as_u32 = i;
545         ip->checksum = 0;
546         ip->checksum = ip4_header_checksum(ip);
547         pnat_node_inline(vm, node, &frame, PNAT_IP4_INPUT, VLIB_RX);
548     }
549
550     test_assert_log(1, "%s", test.name);
551
552     for (i = 0; i < sizeof(rules) / sizeof(rules[0]); i++) {
553         del_translation(&rules[i]);
554     }
555 }
556
557 /*
558  * Unit testing:
559  * 1) Table of packets and expected outcomes. Run through
560  * 2) Performance tests. Measure instructions, cache behaviour etc.
561  */
562 clib_error_t *ip_checksum_init(vlib_main_t *vm);
563
564 int main(int argc, char **argv) {
565
566     clib_mem_init(0, 3ULL << 30);
567
568     vlib_main_init();
569     vlib_main_t *vm = vlib_get_first_main();
570
571     buffers_vector = buffer_init(buffers_vector, 256);
572
573     assert(vlib_node_main_init(vm) == 0);
574
575     ip_checksum_init(vm);
576
577     u32 node_index =
578         vlib_register_node(vm, &pnat_input_node, "%s", pnat_input_node.name);
579     node = vlib_node_get_runtime(vm, node_index);
580     assert(node);
581
582     /* Test API */
583     test_api();
584     test_packets();
585     test_checksum();
586     test_performance();
587 }
588
589 /*
590  * NEW TESTS:
591  * - Chained buffers. Only do rewrite in first buffer
592  * - No interface. Can that really happen?
593  * - IP length shorter than buffer.
594  * - IP length longer than buffer.
595  */