1 /* $QuaggaId: Format:%an, %ai, %h$ $
3 * BGP Multipath Unit Test
4 * Copyright (C) 2010 Google Inc.
6 * This file is part of Quagga
8 * Quagga is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
13 * Quagga is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Quagga; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_table.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_nexthop.h"
41 #include "bgpd/bgp_mpath.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) \
56 printf ("Test failure in %s line %u: %s\n", \
57 __FUNCTION__, __LINE__, #expr); \
58 (res) = TEST_FAILED; \
61 typedef struct testcase_t__ testcase_t
;
63 typedef int (*test_setup_func
)(testcase_t
*);
64 typedef int (*test_run_func
)(testcase_t
*);
65 typedef int (*test_cleanup_func
)(testcase_t
*);
72 test_setup_func setup
;
74 test_cleanup_func cleanup
;
77 /* need these to link in libbgp */
78 struct thread_master
*master
= NULL
;
79 struct zclient
*zclient
;
80 struct zebra_privs_t bgpd_privs
=
89 /* Create fake bgp instance */
91 bgp_create_fake (as_t
*as
, const char *name
)
97 if ( (bgp
= XCALLOC (MTYPE_BGP
, sizeof (struct bgp
))) == NULL
)
101 //bgp->peer_self = peer_new (bgp);
102 //bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
104 bgp
->peer
= list_new ();
105 //bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
107 bgp
->group
= list_new ();
108 //bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
110 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
111 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
113 bgp
->route
[afi
][safi
] = bgp_table_init (afi
, safi
);
114 bgp
->aggregate
[afi
][safi
] = bgp_table_init (afi
, safi
);
115 bgp
->rib
[afi
][safi
] = bgp_table_init (afi
, safi
);
116 bgp
->maxpaths
[afi
][safi
].maxpaths_ebgp
= MULTIPATH_NUM
;
117 bgp
->maxpaths
[afi
][safi
].maxpaths_ibgp
= MULTIPATH_NUM
;
121 bgp
->default_local_pref
= BGP_DEFAULT_LOCAL_PREF
;
122 bgp
->default_holdtime
= BGP_DEFAULT_HOLDTIME
;
123 bgp
->default_keepalive
= BGP_DEFAULT_KEEPALIVE
;
124 bgp
->restart_time
= BGP_DEFAULT_RESTART_TIME
;
125 bgp
->stalepath_time
= BGP_DEFAULT_STALEPATH_TIME
;
130 bgp
->name
= strdup (name
);
135 /*=========================================================
136 * Testcase for maximum-paths configuration
139 setup_bgp_cfg_maximum_paths (testcase_t
*t
)
142 t
->tmp_data
= bgp_create_fake (&asn
, NULL
);
149 run_bgp_cfg_maximum_paths (testcase_t
*t
)
155 int test_result
= TEST_PASSED
;
158 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
159 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
161 /* test bgp_maximum_paths_set */
162 api_result
= bgp_maximum_paths_set (bgp
, afi
, safi
, BGP_PEER_EBGP
, 10, 0);
163 EXPECT_TRUE (api_result
== 0, test_result
);
164 api_result
= bgp_maximum_paths_set (bgp
, afi
, safi
, BGP_PEER_IBGP
, 10, 0);
165 EXPECT_TRUE (api_result
== 0, test_result
);
166 EXPECT_TRUE (bgp
->maxpaths
[afi
][safi
].maxpaths_ebgp
== 10, test_result
);
167 EXPECT_TRUE (bgp
->maxpaths
[afi
][safi
].maxpaths_ibgp
== 10, test_result
);
169 /* test bgp_maximum_paths_unset */
170 api_result
= bgp_maximum_paths_unset (bgp
, afi
, safi
, BGP_PEER_EBGP
);
171 EXPECT_TRUE (api_result
== 0, test_result
);
172 api_result
= bgp_maximum_paths_unset (bgp
, afi
, safi
, BGP_PEER_IBGP
);
173 EXPECT_TRUE (api_result
== 0, test_result
);
174 EXPECT_TRUE ((bgp
->maxpaths
[afi
][safi
].maxpaths_ebgp
==
175 MULTIPATH_NUM
), test_result
);
176 EXPECT_TRUE ((bgp
->maxpaths
[afi
][safi
].maxpaths_ibgp
==
177 MULTIPATH_NUM
), test_result
);
184 cleanup_bgp_cfg_maximum_paths (testcase_t
*t
)
186 return bgp_delete ((struct bgp
*)t
->tmp_data
);
189 testcase_t test_bgp_cfg_maximum_paths
= {
190 .desc
= "Test bgp maximum-paths config",
191 .setup
= setup_bgp_cfg_maximum_paths
,
192 .run
= run_bgp_cfg_maximum_paths
,
193 .cleanup
= cleanup_bgp_cfg_maximum_paths
,
196 /*=========================================================
197 * Testcase for bgp_mp_list
199 struct peer test_mp_list_peer
[] = {
200 { .local_as
= 1, .as
= 2 },
201 { .local_as
= 1, .as
= 2 },
202 { .local_as
= 1, .as
= 2 },
203 { .local_as
= 1, .as
= 2 },
204 { .local_as
= 1, .as
= 2 },
206 int test_mp_list_peer_count
= sizeof (test_mp_list_peer
)/ sizeof (struct peer
);
207 struct attr test_mp_list_attr
[4];
208 struct bgp_info test_mp_list_info
[] = {
209 { .peer
= &test_mp_list_peer
[0], .attr
= &test_mp_list_attr
[0] },
210 { .peer
= &test_mp_list_peer
[1], .attr
= &test_mp_list_attr
[1] },
211 { .peer
= &test_mp_list_peer
[2], .attr
= &test_mp_list_attr
[1] },
212 { .peer
= &test_mp_list_peer
[3], .attr
= &test_mp_list_attr
[2] },
213 { .peer
= &test_mp_list_peer
[4], .attr
= &test_mp_list_attr
[3] },
215 int test_mp_list_info_count
=
216 sizeof (test_mp_list_info
)/sizeof (struct bgp_info
);
219 setup_bgp_mp_list (testcase_t
*t
)
221 test_mp_list_attr
[0].nexthop
.s_addr
= 0x01010101;
222 test_mp_list_attr
[1].nexthop
.s_addr
= 0x02020202;
223 test_mp_list_attr
[2].nexthop
.s_addr
= 0x03030303;
224 test_mp_list_attr
[3].nexthop
.s_addr
= 0x04040404;
226 if ((test_mp_list_peer
[0].su_remote
= sockunion_str2su ("1.1.1.1")) == NULL
)
228 if ((test_mp_list_peer
[1].su_remote
= sockunion_str2su ("2.2.2.2")) == NULL
)
230 if ((test_mp_list_peer
[2].su_remote
= sockunion_str2su ("3.3.3.3")) == NULL
)
232 if ((test_mp_list_peer
[3].su_remote
= sockunion_str2su ("4.4.4.4")) == NULL
)
234 if ((test_mp_list_peer
[4].su_remote
= sockunion_str2su ("5.5.5.5")) == NULL
)
241 run_bgp_mp_list (testcase_t
*t
)
244 struct listnode
*mp_node
;
245 struct bgp_info
*info
;
247 int test_result
= TEST_PASSED
;
248 bgp_mp_list_init (&mp_list
);
249 EXPECT_TRUE (listcount(&mp_list
) == 0, test_result
);
251 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[1]);
252 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[4]);
253 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[2]);
254 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[3]);
255 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[0]);
257 for (i
= 0, mp_node
= mp_list
.head
; i
< test_mp_list_info_count
;
258 i
++, mp_node
= listnextnode(mp_node
))
260 info
= listgetdata(mp_node
);
261 EXPECT_TRUE (info
== &test_mp_list_info
[i
], test_result
);
264 bgp_mp_list_clear (&mp_list
);
265 EXPECT_TRUE (listcount(&mp_list
) == 0, test_result
);
271 cleanup_bgp_mp_list (testcase_t
*t
)
275 for (i
= 0; i
< test_mp_list_peer_count
; i
++)
276 sockunion_free (test_mp_list_peer
[i
].su_remote
);
281 testcase_t test_bgp_mp_list
= {
282 .desc
= "Test bgp_mp_list",
283 .setup
= setup_bgp_mp_list
,
284 .run
= run_bgp_mp_list
,
285 .cleanup
= cleanup_bgp_mp_list
,
288 /*=========================================================
289 * Testcase for bgp_info_mpath_update
292 struct bgp_node test_rn
;
295 setup_bgp_info_mpath_update (testcase_t
*t
)
298 str2prefix ("42.1.1.0/24", &test_rn
.p
);
299 setup_bgp_mp_list (t
);
300 for (i
= 0; i
< test_mp_list_info_count
; i
++)
301 bgp_info_add (&test_rn
, &test_mp_list_info
[i
]);
306 run_bgp_info_mpath_update (testcase_t
*t
)
308 struct bgp_info
*new_best
, *old_best
, *mpath
;
310 struct bgp_maxpaths_cfg mp_cfg
= { 3, 3 };
311 int test_result
= TEST_PASSED
;
312 bgp_mp_list_init (&mp_list
);
313 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[4]);
314 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[3]);
315 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[0]);
316 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[1]);
317 new_best
= &test_mp_list_info
[3];
319 bgp_info_mpath_update (&test_rn
, new_best
, old_best
, &mp_list
, &mp_cfg
);
320 bgp_mp_list_clear (&mp_list
);
321 EXPECT_TRUE (bgp_info_mpath_count (new_best
) == 2, test_result
);
322 mpath
= bgp_info_mpath_first (new_best
);
323 EXPECT_TRUE (mpath
== &test_mp_list_info
[0], test_result
);
324 EXPECT_TRUE (CHECK_FLAG (mpath
->flags
, BGP_INFO_MULTIPATH
), test_result
);
325 mpath
= bgp_info_mpath_next (mpath
);
326 EXPECT_TRUE (mpath
== &test_mp_list_info
[1], test_result
);
327 EXPECT_TRUE (CHECK_FLAG (mpath
->flags
, BGP_INFO_MULTIPATH
), test_result
);
329 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[0]);
330 bgp_mp_list_add (&mp_list
, &test_mp_list_info
[1]);
331 new_best
= &test_mp_list_info
[0];
332 old_best
= &test_mp_list_info
[3];
333 bgp_info_mpath_update (&test_rn
, new_best
, old_best
, &mp_list
, &mp_cfg
);
334 bgp_mp_list_clear (&mp_list
);
335 EXPECT_TRUE (bgp_info_mpath_count (new_best
) == 1, test_result
);
336 mpath
= bgp_info_mpath_first (new_best
);
337 EXPECT_TRUE (mpath
== &test_mp_list_info
[1], test_result
);
338 EXPECT_TRUE (CHECK_FLAG (mpath
->flags
, BGP_INFO_MULTIPATH
), test_result
);
339 EXPECT_TRUE (!CHECK_FLAG (test_mp_list_info
[0].flags
, BGP_INFO_MULTIPATH
),
346 cleanup_bgp_info_mpath_update (testcase_t
*t
)
350 for (i
= 0; i
< test_mp_list_peer_count
; i
++)
351 sockunion_free (test_mp_list_peer
[i
].su_remote
);
356 testcase_t test_bgp_info_mpath_update
= {
357 .desc
= "Test bgp_info_mpath_update",
358 .setup
= setup_bgp_info_mpath_update
,
359 .run
= run_bgp_info_mpath_update
,
360 .cleanup
= cleanup_bgp_info_mpath_update
,
363 /*=========================================================
364 * Set up testcase vector
366 testcase_t
*all_tests
[] = {
367 &test_bgp_cfg_maximum_paths
,
369 &test_bgp_info_mpath_update
,
372 int all_tests_count
= (sizeof(all_tests
)/sizeof(testcase_t
*));
374 /*=========================================================
375 * Test Driver Functions
378 global_test_init (void)
381 master
= thread_master_create ();
382 zclient
= zclient_new(master
);
385 bgp_option_set (BGP_OPT_NO_LISTEN
);
387 if (fileno (stdout
) >= 0)
388 tty
= isatty (fileno (stdout
));
393 global_test_cleanup (void)
396 zclient_free (zclient
);
397 thread_master_free (master
);
402 display_result (testcase_t
*test
, int result
)
405 printf ("%s: %s\n", test
->desc
, result
== TEST_PASSED
? OK
: FAILED
);
407 printf ("%s: %s\n", test
->desc
, result
== TEST_PASSED
? "OK" : "FAILED");
411 setup_test (testcase_t
*t
)
420 cleanup_test (testcase_t
*t
)
424 res
= t
->cleanup (t
);
429 run_tests (testcase_t
*tests
[], int num_tests
, int *pass_count
, int *fail_count
)
431 int test_index
, result
;
432 testcase_t
*cur_test
;
434 *pass_count
= *fail_count
= 0;
436 for (test_index
= 0; test_index
< num_tests
; test_index
++)
438 cur_test
= tests
[test_index
];
441 printf ("error: test %d has no description!\n", test_index
);
446 printf ("error: test %s has no run function!\n", cur_test
->desc
);
449 if (setup_test (cur_test
) != 0)
451 printf ("error: setup failed for test %s\n", cur_test
->desc
);
454 result
= cur_test
->run (cur_test
);
455 if (result
== TEST_PASSED
)
459 display_result (cur_test
, result
);
460 if (cleanup_test (cur_test
) != 0)
462 printf ("error: cleanup failed for test %s\n", cur_test
->desc
);
471 int pass_count
, fail_count
;
475 printf("BGP Multipath Tests Run at %s", ctime(&cur_time
));
476 if (global_test_init () != 0)
478 printf("Global init failed. Terminating.\n");
481 run_tests (all_tests
, all_tests_count
, &pass_count
, &fail_count
);
482 global_test_cleanup ();
483 printf("Total pass/fail: %d/%d\n", pass_count
, fail_count
);