• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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