1 #include <netlink-private/types.h>
2 #include <netlink/route/cls/ematch.h>
3
4 #include <linux/netlink.h>
5
6 #include <stdio.h>
7 #include <time.h>
8
9 #include <check.h>
10 #include "util.h"
11
12 #define MAX_DEPTH 6
13 #define MAX_CHILDREN 5
14
15 static int current_depth = 0;
16 static int id = 1;
17 static long long array_size = 0;
18
19 static int *src_result = NULL, *dst_result = NULL;
20
my_pow(long long x,long long y)21 static long long my_pow(long long x, long long y)
22 {
23 int ret = x;
24
25 if (y == 0)
26 return 1;
27
28 if (y < 0 || x == 0)
29 return 0;
30
31 while(--y) {
32 ret *= x;
33 }
34
35 return ret;
36 }
37
generate_random(long int max)38 static long int generate_random(long int max)
39 {
40 srandom(time(NULL) + id);
41 return (random() % max);
42 }
43
build_children(struct nl_list_head * parent)44 static int build_children(struct nl_list_head *parent)
45 {
46 int i, num = 0;
47 struct rtnl_ematch *child = NULL;
48
49 if (!parent)
50 return 0;
51
52 if (++current_depth > MAX_DEPTH) {
53 --current_depth;
54 return 0;
55 }
56
57 num = generate_random(MAX_CHILDREN + 1);
58 for (i = 0; i < num; ++i) {
59 child = rtnl_ematch_alloc();
60 if (!child) {
61 printf("Mem alloc error\n");
62 exit(1);
63 }
64 build_children(&child->e_childs);
65 child->e_id = id++;
66 nl_list_add_tail(&child->e_list, parent);
67 }
68
69 --current_depth;
70 return 0;
71 }
72
build_src_cgroup(struct rtnl_ematch_tree * tree)73 static void build_src_cgroup(struct rtnl_ematch_tree *tree)
74 {
75 build_children(&tree->et_list);
76 }
77
dump_ematch_list(struct nl_list_head * head,int * result,int * index)78 static void dump_ematch_list(struct nl_list_head *head, int *result, int *index)
79 {
80 struct rtnl_ematch *pos = NULL;
81
82 nl_list_for_each_entry(pos, head, e_list) {
83 if (!nl_list_empty(&pos->e_childs))
84 dump_ematch_list(&pos->e_childs, result, index);
85 result[*index] = pos->e_id;
86 (*index)++;
87 }
88 }
89
dump_ematch_tree(struct rtnl_ematch_tree * tree,int * result,int * index)90 static void dump_ematch_tree(struct rtnl_ematch_tree *tree, int *result, int *index)
91 {
92 if (!tree)
93 return;
94
95 dump_ematch_list(&tree->et_list, result, index);
96 }
97
compare(int * r1,int * r2,int len)98 static int compare(int *r1, int *r2, int len)
99 {
100 int i = 0;
101 for (i = 0; i < len; ++i) {
102 if (r1[i] != r2[i])
103 return -1;
104 }
105 return 0;
106 }
107
START_TEST(ematch_tree_clone)108 START_TEST(ematch_tree_clone)
109 {
110 struct rtnl_ematch_tree *src = NULL, *dst = NULL;
111 int i = 0, j = 0;
112
113 array_size = (MAX_DEPTH * my_pow(MAX_CHILDREN, MAX_DEPTH)) / 2;
114 src_result = calloc(4, array_size);
115 dst_result = calloc(4, array_size);
116
117 src = rtnl_ematch_tree_alloc(2);
118
119 build_src_cgroup(src);
120 dump_ematch_tree(src, src_result, &i);
121
122 dst = rtnl_ematch_tree_clone(src);
123 dump_ematch_tree(dst, dst_result, &j);
124
125 fail_if(!dst);
126 fail_if(i != j);
127 fail_if(compare(src_result, dst_result, i));
128
129 free(src_result);
130 free(dst_result);
131 }
132 END_TEST
133
make_nl_ematch_tree_clone_suite(void)134 Suite *make_nl_ematch_tree_clone_suite(void)
135 {
136 Suite *suite = suite_create("Clone ematch tree");
137
138 TCase *ematch_tree = tcase_create("Core");
139 tcase_add_test(ematch_tree, ematch_tree_clone);
140 suite_add_tcase(suite, ematch_tree);
141
142 return suite;
143 }
144