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