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