2 * BGP Multipath Unit Test
3 * Copyright (C) 2010 Google Inc.
5 * This file is part of Quagga
7 * Quagga is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * Quagga is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "bgpd/bgpd.h"
35 #include "bgpd/bgp_table.h"
36 #include "bgpd/bgp_route.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_nexthop.h"
39 #include "bgpd/bgp_mpath.h"
40 #include "bgpd/bgp_evpn.h"
41 #include "bgpd/bgp_network.h"
43 #define VT100_RESET "\x1b[0m"
44 #define VT100_RED "\x1b[31m"
45 #define VT100_GREEN "\x1b[32m"
46 #define VT100_YELLOW "\x1b[33m"
47 #define OK VT100_GREEN "OK" VT100_RESET
48 #define FAILED VT100_RED "failed" VT100_RESET
51 #define TEST_FAILED -1
53 #define EXPECT_TRUE(expr, res) \
55 printf("Test failure in %s line %u: %s\n", __func__, __LINE__, \
57 (res) = TEST_FAILED; \
60 typedef struct testcase_t__ testcase_t
;
62 typedef int (*test_setup_func
)(testcase_t
*);
63 typedef int (*test_run_func
)(testcase_t
*);
64 typedef int (*test_cleanup_func
)(testcase_t
*);
71 test_setup_func setup
;
73 test_cleanup_func cleanup
;
76 /* need these to link in libbgp */
77 struct thread_master
*master
= NULL
;
78 extern struct zclient
*zclient
;
79 struct zebra_privs_t bgpd_privs
= {
87 /* Create fake bgp instance */
88 static struct bgp
*bgp_create_fake(as_t
*as
, const char *name
)
94 if ((bgp
= XCALLOC(MTYPE_BGP
, sizeof(struct bgp
))) == NULL
)
98 // bgp->peer_self = peer_new (bgp);
99 // bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static
102 bgp
->peer
= list_new();
103 // bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
105 bgp
->group
= list_new();
106 // bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
109 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
110 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
111 bgp
->route
[afi
][safi
] = bgp_table_init(bgp
, afi
, safi
);
112 bgp
->aggregate
[afi
][safi
] = bgp_table_init(
114 bgp
->rib
[afi
][safi
] = bgp_table_init(bgp
, afi
, safi
);
115 bgp
->maxpaths
[afi
][safi
].maxpaths_ebgp
= MULTIPATH_NUM
;
116 bgp
->maxpaths
[afi
][safi
].maxpaths_ibgp
= MULTIPATH_NUM
;
120 bgp
->default_local_pref
= BGP_DEFAULT_LOCAL_PREF
;
121 bgp
->default_holdtime
= BGP_DEFAULT_HOLDTIME
;
122 bgp
->default_keepalive
= BGP_DEFAULT_KEEPALIVE
;
123 bgp
->restart_time
= BGP_DEFAULT_RESTART_TIME
;
124 bgp
->stalepath_time
= BGP_DEFAULT_STALEPATH_TIME
;
129 bgp
->name
= strdup(name
);
134 /*=========================================================
135 * Testcase for maximum-paths configuration
137 static int setup_bgp_cfg_maximum_paths(testcase_t
*t
)
140 t
->tmp_data
= bgp_create_fake(&asn
, NULL
);
146 static int run_bgp_cfg_maximum_paths(testcase_t
*t
)
152 int test_result
= TEST_PASSED
;
155 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
156 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
157 /* test bgp_maximum_paths_set */
158 api_result
= bgp_maximum_paths_set(
159 bgp
, afi
, safi
, BGP_PEER_EBGP
, 10, 0);
160 EXPECT_TRUE(api_result
== 0, test_result
);
161 api_result
= bgp_maximum_paths_set(
162 bgp
, afi
, safi
, BGP_PEER_IBGP
, 10, 0);
163 EXPECT_TRUE(api_result
== 0, test_result
);
164 EXPECT_TRUE(bgp
->maxpaths
[afi
][safi
].maxpaths_ebgp
167 EXPECT_TRUE(bgp
->maxpaths
[afi
][safi
].maxpaths_ibgp
171 /* test bgp_maximum_paths_unset */
172 api_result
= bgp_maximum_paths_unset(bgp
, afi
, safi
,
174 EXPECT_TRUE(api_result
== 0, test_result
);
175 api_result
= bgp_maximum_paths_unset(bgp
, afi
, safi
,
177 EXPECT_TRUE(api_result
== 0, test_result
);
178 EXPECT_TRUE((bgp
->maxpaths
[afi
][safi
].maxpaths_ebgp
181 EXPECT_TRUE((bgp
->maxpaths
[afi
][safi
].maxpaths_ibgp
189 static int cleanup_bgp_cfg_maximum_paths(testcase_t
*t
)
191 return bgp_delete((struct bgp
*)t
->tmp_data
);
194 testcase_t test_bgp_cfg_maximum_paths
= {
195 .desc
= "Test bgp maximum-paths config",
196 .setup
= setup_bgp_cfg_maximum_paths
,
197 .run
= run_bgp_cfg_maximum_paths
,
198 .cleanup
= cleanup_bgp_cfg_maximum_paths
,
201 /*=========================================================
202 * Testcase for bgp_mp_list
204 struct peer test_mp_list_peer
[] = {
205 {.local_as
= 1, .as
= 2}, {.local_as
= 1, .as
= 2},
206 {.local_as
= 1, .as
= 2}, {.local_as
= 1, .as
= 2},
207 {.local_as
= 1, .as
= 2},
209 int test_mp_list_peer_count
= array_size(test_mp_list_peer
);
210 struct attr test_mp_list_attr
[4];
211 struct bgp_path_info test_mp_list_info
[] = {
212 {.peer
= &test_mp_list_peer
[0], .attr
= &test_mp_list_attr
[0]},
213 {.peer
= &test_mp_list_peer
[1], .attr
= &test_mp_list_attr
[1]},
214 {.peer
= &test_mp_list_peer
[2], .attr
= &test_mp_list_attr
[1]},
215 {.peer
= &test_mp_list_peer
[3], .attr
= &test_mp_list_attr
[2]},
216 {.peer
= &test_mp_list_peer
[4], .attr
= &test_mp_list_attr
[3]},
218 int test_mp_list_info_count
= array_size(test_mp_list_info
);
220 static int setup_bgp_mp_list(testcase_t
*t
)
222 test_mp_list_attr
[0].nexthop
.s_addr
= 0x01010101;
223 test_mp_list_attr
[1].nexthop
.s_addr
= 0x02020202;
224 test_mp_list_attr
[2].nexthop
.s_addr
= 0x03030303;
225 test_mp_list_attr
[3].nexthop
.s_addr
= 0x04040404;
227 if ((test_mp_list_peer
[0].su_remote
= sockunion_str2su("1.1.1.1"))
230 if ((test_mp_list_peer
[1].su_remote
= sockunion_str2su("2.2.2.2"))
233 if ((test_mp_list_peer
[2].su_remote
= sockunion_str2su("3.3.3.3"))
236 if ((test_mp_list_peer
[3].su_remote
= sockunion_str2su("4.4.4.4"))
239 if ((test_mp_list_peer
[4].su_remote
= sockunion_str2su("5.5.5.5"))
246 static int run_bgp_mp_list(testcase_t
*t
)
249 struct listnode
*mp_node
;
250 struct bgp_path_info
*info
;
252 int test_result
= TEST_PASSED
;
253 bgp_mp_list_init(&mp_list
);
254 EXPECT_TRUE(listcount(&mp_list
) == 0, test_result
);
256 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[1]);
257 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[4]);
258 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[2]);
259 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[3]);
260 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[0]);
262 for (i
= 0, mp_node
= mp_list
.head
; i
< test_mp_list_info_count
;
263 i
++, mp_node
= listnextnode(mp_node
)) {
264 info
= listgetdata(mp_node
);
265 EXPECT_TRUE(info
== &test_mp_list_info
[i
], test_result
);
268 bgp_mp_list_clear(&mp_list
);
269 EXPECT_TRUE(listcount(&mp_list
) == 0, test_result
);
274 static int cleanup_bgp_mp_list(testcase_t
*t
)
278 for (i
= 0; i
< test_mp_list_peer_count
; i
++)
279 sockunion_free(test_mp_list_peer
[i
].su_remote
);
284 testcase_t test_bgp_mp_list
= {
285 .desc
= "Test bgp_mp_list",
286 .setup
= setup_bgp_mp_list
,
287 .run
= run_bgp_mp_list
,
288 .cleanup
= cleanup_bgp_mp_list
,
291 /*=========================================================
292 * Testcase for bgp_path_info_mpath_update
295 struct bgp_node test_rn
;
297 static int setup_bgp_path_info_mpath_update(testcase_t
*t
)
301 struct bgp_table
*rt
;
302 struct route_node
*rt_node
;
305 t
->tmp_data
= bgp_create_fake(&asn
, NULL
);
310 rt
= bgp
->rib
[AFI_IP
][SAFI_UNICAST
];
315 str2prefix("42.1.1.0/24", &test_rn
.p
);
316 rt_node
= bgp_node_to_rnode(&test_rn
);
317 memcpy((struct route_table
*)&rt_node
->table
, &rt
->route_table
,
318 sizeof(struct route_table
));
319 setup_bgp_mp_list(t
);
320 for (i
= 0; i
< test_mp_list_info_count
; i
++)
321 bgp_path_info_add(&test_rn
, &test_mp_list_info
[i
]);
325 static int run_bgp_path_info_mpath_update(testcase_t
*t
)
327 struct bgp_path_info
*new_best
, *old_best
, *mpath
;
329 struct bgp_maxpaths_cfg mp_cfg
= {3, 3};
330 int test_result
= TEST_PASSED
;
331 bgp_mp_list_init(&mp_list
);
332 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[4]);
333 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[3]);
334 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[0]);
335 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[1]);
336 new_best
= &test_mp_list_info
[3];
338 bgp_path_info_mpath_update(&test_rn
, new_best
, old_best
, &mp_list
,
340 bgp_mp_list_clear(&mp_list
);
341 EXPECT_TRUE(bgp_path_info_mpath_count(new_best
) == 2, test_result
);
342 mpath
= bgp_path_info_mpath_first(new_best
);
343 EXPECT_TRUE(mpath
== &test_mp_list_info
[0], test_result
);
344 EXPECT_TRUE(CHECK_FLAG(mpath
->flags
, BGP_PATH_MULTIPATH
), test_result
);
345 mpath
= bgp_path_info_mpath_next(mpath
);
346 EXPECT_TRUE(mpath
== &test_mp_list_info
[1], test_result
);
347 EXPECT_TRUE(CHECK_FLAG(mpath
->flags
, BGP_PATH_MULTIPATH
), test_result
);
349 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[0]);
350 bgp_mp_list_add(&mp_list
, &test_mp_list_info
[1]);
351 new_best
= &test_mp_list_info
[0];
352 old_best
= &test_mp_list_info
[3];
353 bgp_path_info_mpath_update(&test_rn
, new_best
, old_best
, &mp_list
,
355 bgp_mp_list_clear(&mp_list
);
356 EXPECT_TRUE(bgp_path_info_mpath_count(new_best
) == 1, test_result
);
357 mpath
= bgp_path_info_mpath_first(new_best
);
358 EXPECT_TRUE(mpath
== &test_mp_list_info
[1], test_result
);
359 EXPECT_TRUE(CHECK_FLAG(mpath
->flags
, BGP_PATH_MULTIPATH
), test_result
);
360 EXPECT_TRUE(!CHECK_FLAG(test_mp_list_info
[0].flags
, BGP_PATH_MULTIPATH
),
366 static int cleanup_bgp_path_info_mpath_update(testcase_t
*t
)
370 for (i
= 0; i
< test_mp_list_peer_count
; i
++)
371 sockunion_free(test_mp_list_peer
[i
].su_remote
);
373 return bgp_delete((struct bgp
*)t
->tmp_data
);
376 testcase_t test_bgp_path_info_mpath_update
= {
377 .desc
= "Test bgp_path_info_mpath_update",
378 .setup
= setup_bgp_path_info_mpath_update
,
379 .run
= run_bgp_path_info_mpath_update
,
380 .cleanup
= cleanup_bgp_path_info_mpath_update
,
383 /*=========================================================
384 * Set up testcase vector
386 testcase_t
*all_tests
[] = {
387 &test_bgp_cfg_maximum_paths
, &test_bgp_mp_list
,
388 &test_bgp_path_info_mpath_update
,
391 int all_tests_count
= array_size(all_tests
);
393 /*=========================================================
394 * Test Driver Functions
396 static int global_test_init(void)
399 master
= thread_master_create(NULL
);
400 zclient
= zclient_new(master
, &zclient_options_default
);
401 bgp_master_init(master
, BGP_SOCKET_SNDBUF_SIZE
);
402 vrf_init(NULL
, NULL
, NULL
, NULL
, NULL
);
403 bgp_option_set(BGP_OPT_NO_LISTEN
);
405 if (fileno(stdout
) >= 0)
406 tty
= isatty(fileno(stdout
));
410 static int global_test_cleanup(void)
413 zclient_free(zclient
);
414 thread_master_free(master
);
418 static void display_result(testcase_t
*test
, int result
)
421 printf("%s: %s\n", test
->desc
,
422 result
== TEST_PASSED
? OK
: FAILED
);
424 printf("%s: %s\n", test
->desc
,
425 result
== TEST_PASSED
? "OK" : "FAILED");
428 static int setup_test(testcase_t
*t
)
436 static int cleanup_test(testcase_t
*t
)
444 static void run_tests(testcase_t
*tests
[], int num_tests
, int *pass_count
,
447 int test_index
, result
;
448 testcase_t
*cur_test
;
450 *pass_count
= *fail_count
= 0;
452 for (test_index
= 0; test_index
< num_tests
; test_index
++) {
453 cur_test
= tests
[test_index
];
454 if (!cur_test
->desc
) {
455 printf("error: test %d has no description!\n",
459 if (!cur_test
->run
) {
460 printf("error: test %s has no run function!\n",
464 if (setup_test(cur_test
) != 0) {
465 printf("error: setup failed for test %s\n",
469 result
= cur_test
->run(cur_test
);
470 if (result
== TEST_PASSED
)
474 display_result(cur_test
, result
);
475 if (cleanup_test(cur_test
) != 0) {
476 printf("error: cleanup failed for test %s\n",
485 int pass_count
, fail_count
;
489 printf("BGP Multipath Tests Run at %s", ctime(&cur_time
));
490 if (global_test_init() != 0) {
491 printf("Global init failed. Terminating.\n");
494 run_tests(all_tests
, all_tests_count
, &pass_count
, &fail_count
);
495 global_test_cleanup();
496 printf("Total pass/fail: %d/%d\n", pass_count
, fail_count
);