Skip to content

Commit f4d68e9

Browse files
committed
[nh] Add comprehensive test-suite for all lib/route/nh API-calls
Test as much as possible, positive and negative conditions. Signed-off-by: Christoph Paasch <[email protected]>
1 parent 79d1abd commit f4d68e9

File tree

4 files changed

+191
-0
lines changed

4 files changed

+191
-0
lines changed

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,7 @@ tests_check_all_SOURCES = \
10651065
tests/cksuite-all-ematch-tree-clone.c \
10661066
tests/cksuite-all-netns.c \
10671067
tests/cksuite-link-ip6tnl.c \
1068+
tests/cksuite-route-nh.c \
10681069
tests/cksuite-all.h \
10691070
$(NULL)
10701071

tests/check-all.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ int main(int argc, char *argv[])
2828
srunner_add_suite(runner, make_nl_ematch_tree_clone_suite());
2929
srunner_add_suite(runner, make_nl_netns_suite());
3030
srunner_add_suite(runner, make_nl_ip6_tnl_suite());
31+
srunner_add_suite(runner, make_nl_route_nh_suite());
3132

3233
srunner_run_all(runner, CK_ENV);
3334

tests/cksuite-all.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ Suite *make_nl_addr_suite(void);
1010
Suite *make_nl_ematch_tree_clone_suite(void);
1111
Suite *make_nl_netns_suite(void);
1212
Suite *make_nl_ip6_tnl_suite(void);
13+
Suite *make_nl_route_nh_suite(void);
1314

1415
#endif /* __LIBNL3_TESTS_CHECK_ALL_H__ */

tests/cksuite-route-nh.c

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/* SPDX-License-Identifier: LGPL-2.1-only */
2+
3+
/*
4+
* Tests for include/netlink/route/nh.h getters and setters.
5+
*
6+
* We cover two aspects:
7+
* 1. Pure userspace logic – manipulating an allocated rtnl_nh object and
8+
* validating all getters, including negative/error conditions.
9+
* 2. Kernel round-trip – create a real nexthop in a private network
10+
* namespace, query it back via the cache and verify attributes round-trip.
11+
*/
12+
13+
#include "nl-default.h"
14+
15+
#include <linux/nexthop.h>
16+
17+
#include <netlink/route/nh.h>
18+
19+
#include "cksuite-all.h"
20+
21+
/*****************************************************************************/
22+
/* Userspace comprehensive test covering all API calls */
23+
24+
START_TEST(test_api_set_get_all)
25+
{
26+
_nl_auto_rtnl_nh struct rtnl_nh *nh = NULL;
27+
_nl_auto_nl_addr struct nl_addr *gw4 = NULL;
28+
_nl_auto_nl_addr struct nl_addr *gw6 = NULL;
29+
nl_nh_group_info_t entries[2];
30+
uint32_t tmp32;
31+
32+
nh = rtnl_nh_alloc();
33+
ck_assert_ptr_nonnull(nh);
34+
35+
/* Family set/get + negative on NULL */
36+
ck_assert_int_eq(rtnl_nh_get_family(nh), AF_UNSPEC);
37+
ck_assert_int_eq(rtnl_nh_set_family(nh, AF_INET6), 0);
38+
ck_assert_int_eq(rtnl_nh_get_family(nh), AF_INET6);
39+
ck_assert_int_eq(rtnl_nh_set_family(NULL, AF_INET), -NLE_INVAL);
40+
ck_assert_int_eq(rtnl_nh_get_family(NULL), -NLE_INVAL);
41+
42+
/* ID get before set -> -NLE_INVAL; set/get/clear */
43+
ck_assert_int_eq(rtnl_nh_get_id(nh), -NLE_INVAL);
44+
ck_assert_int_eq(rtnl_nh_set_id(nh, 1001), 0);
45+
ck_assert_int_eq(rtnl_nh_get_id(nh), 1001);
46+
ck_assert_int_eq(rtnl_nh_set_id(nh, 0), 0);
47+
ck_assert_int_eq(rtnl_nh_get_id(nh), -NLE_INVAL);
48+
ck_assert_int_eq(rtnl_nh_set_id(NULL, 1), -NLE_INVAL);
49+
50+
/* OIF get before set is 0; set/get; clear; negative on NULL */
51+
ck_assert_int_eq(rtnl_nh_get_oif(nh), 0);
52+
ck_assert_int_eq(rtnl_nh_set_oif(nh, 1234), 0);
53+
ck_assert_int_eq(rtnl_nh_get_oif(nh), 1234);
54+
ck_assert_int_eq(rtnl_nh_set_oif(nh, 0), 0);
55+
ck_assert_int_eq(rtnl_nh_get_oif(nh), 0);
56+
ck_assert_int_eq(rtnl_nh_set_oif(NULL, 1), -NLE_INVAL);
57+
58+
/* Gateway get/set; start NULL, set v4 then replace with v6 */
59+
ck_assert_ptr_eq(rtnl_nh_get_gateway(nh), NULL);
60+
ck_assert_int_eq(nl_addr_parse("192.0.2.1", AF_INET, &gw4), 0);
61+
ck_assert_int_eq(rtnl_nh_set_gateway(NULL, gw4), -NLE_INVAL);
62+
ck_assert_int_eq(rtnl_nh_set_gateway(nh, NULL), 0);
63+
ck_assert_int_eq(rtnl_nh_set_gateway(nh, gw4), 0);
64+
65+
ck_assert_ptr_nonnull(rtnl_nh_get_gateway(nh));
66+
ck_assert_int_eq(nl_addr_parse("2001:db8::1", AF_INET6, &gw6), 0);
67+
68+
ck_assert_int_eq(rtnl_nh_set_gateway(nh, gw6), 0);
69+
70+
/* Previous set_gateway replaced the old one. It should no more be shared now */
71+
ck_assert_int_eq(nl_addr_shared(gw4), 0);
72+
73+
ck_assert_int_eq(nl_addr_get_family(rtnl_nh_get_gateway(nh)), AF_INET6);
74+
75+
ck_assert_int_eq(rtnl_nh_set_gateway(nh, NULL), 0);
76+
ck_assert_ptr_eq(rtnl_nh_get_gateway(nh), NULL);
77+
78+
79+
/* FDB flag set/clear */
80+
ck_assert_int_eq(rtnl_nh_get_fdb(nh), 0);
81+
ck_assert_int_eq(rtnl_nh_set_fdb(nh, 1), 0);
82+
ck_assert_int_ne(rtnl_nh_get_fdb(nh), 1);
83+
ck_assert_int_eq(rtnl_nh_set_fdb(nh, 0), 0);
84+
ck_assert_int_eq(rtnl_nh_get_fdb(nh), 0);
85+
86+
/* Group getters before set -> missing */
87+
ck_assert_int_eq(rtnl_nh_get_group_size(nh), -NLE_MISSING_ATTR);
88+
ck_assert_int_eq(rtnl_nh_get_group_entry(nh, 0), -NLE_MISSING_ATTR);
89+
90+
/* Group setter - negative tests */
91+
ck_assert_int_eq(rtnl_nh_set_group(NULL, entries, 1), -NLE_INVAL);
92+
ck_assert_int_eq(rtnl_nh_set_group(nh, NULL, 1), -NLE_INVAL);
93+
ck_assert_int_eq(rtnl_nh_set_group(nh, entries, 0), -NLE_INVAL);
94+
95+
/* Group set/get and indexing */
96+
entries[0].nh_id = 10;
97+
entries[0].weight = 1;
98+
entries[1].nh_id = 20;
99+
entries[1].weight = 2;
100+
ck_assert_int_eq(rtnl_nh_set_group(nh, entries, 2), 0);
101+
ck_assert_int_eq(rtnl_nh_get_group_size(nh), 2);
102+
ck_assert_int_eq(rtnl_nh_get_group_entry(nh, -1), -NLE_INVAL);
103+
ck_assert_int_eq(rtnl_nh_get_group_entry(nh, 2), -NLE_INVAL);
104+
ck_assert_int_eq(rtnl_nh_get_group_entry(nh, 0), 10);
105+
ck_assert_int_eq(rtnl_nh_get_group_entry(nh, 1), 20);
106+
107+
/* Replace group with a different size */
108+
ck_assert_int_eq(rtnl_nh_set_group(nh, entries, 1), 0);
109+
ck_assert_int_eq(rtnl_nh_get_group_size(nh), 1);
110+
ck_assert_int_eq(rtnl_nh_get_group_entry(nh, 0), 10);
111+
ck_assert_int_eq(rtnl_nh_get_group_entry(nh, 1), -NLE_INVAL);
112+
113+
/* Remove group */
114+
ck_assert_int_eq(rtnl_nh_set_group(nh, NULL, 0), 0);
115+
ck_assert_int_eq(rtnl_nh_get_group_size(nh), -NLE_MISSING_ATTR);
116+
117+
/* Group type get negative before set, set/get after */
118+
ck_assert_int_eq(rtnl_nh_get_group_type(NULL), -NLE_INVAL);
119+
ck_assert_int_eq(rtnl_nh_get_group_type(nh), -NLE_INVAL);
120+
ck_assert_int_eq(rtnl_nh_set_group_type(NULL, NEXTHOP_GRP_TYPE_MPATH),
121+
-NLE_INVAL);
122+
ck_assert_int_eq(rtnl_nh_set_group_type(nh, NEXTHOP_GRP_TYPE_MPATH), 0);
123+
ck_assert_int_eq(rtnl_nh_get_group_type(nh), NEXTHOP_GRP_TYPE_MPATH);
124+
ck_assert_int_eq(rtnl_nh_set_group_type(NULL, NEXTHOP_GRP_TYPE_RES),
125+
-NLE_INVAL);
126+
127+
/* Resilient group setters/getters negative when type != RES */
128+
ck_assert_int_eq(rtnl_nh_set_res_group_bucket_size(nh, 64), -NLE_INVAL);
129+
ck_assert_int_eq(rtnl_nh_get_res_group_bucket_size(nh), -NLE_INVAL);
130+
ck_assert_int_eq(rtnl_nh_set_res_group_idle_timer(nh, 10), -NLE_INVAL);
131+
ck_assert_int_eq(rtnl_nh_get_res_group_idle_timer(nh, &tmp32),
132+
-NLE_INVAL);
133+
ck_assert_int_eq(rtnl_nh_get_res_group_idle_timer(nh, NULL),
134+
-NLE_INVAL);
135+
ck_assert_int_eq(rtnl_nh_set_res_group_unbalanced_timer(nh, 20),
136+
-NLE_INVAL);
137+
ck_assert_int_eq(rtnl_nh_get_res_group_unbalanced_timer(nh, &tmp32),
138+
-NLE_INVAL);
139+
ck_assert_int_eq(rtnl_nh_get_res_group_unbalanced_timer(nh, NULL),
140+
-NLE_INVAL);
141+
142+
/* Switch to resilient type and test getters/setters */
143+
ck_assert_int_eq(rtnl_nh_set_group_type(nh, NEXTHOP_GRP_TYPE_RES), 0);
144+
145+
/* Bucket size: missing before set, then set/get, then clear */
146+
ck_assert_int_eq(rtnl_nh_get_res_group_bucket_size(nh),
147+
-NLE_MISSING_ATTR);
148+
ck_assert_int_eq(rtnl_nh_set_res_group_bucket_size(nh, 128), 0);
149+
ck_assert_int_eq(rtnl_nh_get_res_group_bucket_size(nh), 128);
150+
ck_assert_int_eq(rtnl_nh_set_res_group_bucket_size(nh, 0), 0);
151+
ck_assert_int_eq(rtnl_nh_get_res_group_bucket_size(nh),
152+
-NLE_MISSING_ATTR);
153+
154+
/* Idle timer: missing before set, then set/get; out NULL negative */
155+
tmp32 = 0;
156+
ck_assert_int_eq(rtnl_nh_get_res_group_idle_timer(nh, &tmp32),
157+
-NLE_MISSING_ATTR);
158+
ck_assert_int_eq(rtnl_nh_set_res_group_idle_timer(nh, 15), 0);
159+
tmp32 = 0;
160+
ck_assert_int_eq(rtnl_nh_get_res_group_idle_timer(nh, &tmp32), 0);
161+
ck_assert_int_eq(tmp32, 15U);
162+
ck_assert_int_eq(rtnl_nh_get_res_group_idle_timer(nh, NULL),
163+
-NLE_INVAL);
164+
165+
/* Unbalanced timer: missing before set, then set/get; out NULL negative */
166+
tmp32 = 0;
167+
ck_assert_int_eq(rtnl_nh_get_res_group_unbalanced_timer(nh, &tmp32),
168+
-NLE_MISSING_ATTR);
169+
ck_assert_int_eq(rtnl_nh_set_res_group_unbalanced_timer(nh, 25), 0);
170+
tmp32 = 0;
171+
ck_assert_int_eq(rtnl_nh_get_res_group_unbalanced_timer(nh, &tmp32), 0);
172+
ck_assert_int_eq(tmp32, 25U);
173+
ck_assert_int_eq(rtnl_nh_get_res_group_unbalanced_timer(nh, NULL),
174+
-NLE_INVAL);
175+
}
176+
END_TEST
177+
178+
Suite *make_nl_route_nh_suite(void)
179+
{
180+
Suite *suite = suite_create("route-nh");
181+
TCase *tc_api = tcase_create("Userspace-API");
182+
183+
/* Comprehensive API setter/getter test (userspace only) */
184+
tcase_add_test(tc_api, test_api_set_get_all);
185+
suite_add_tcase(suite, tc_api);
186+
187+
return suite;
188+
}

0 commit comments

Comments
 (0)