2 * BGP Peer Attribute Unit Tests
3 * Copyright (C) 2018 Pascal Mathis
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "bgpd/bgpd.h"
24 #include "bgpd/bgp_attr.h"
25 #include "bgpd/bgp_regex.h"
26 #include "bgpd/bgp_clist.h"
27 #include "bgpd/bgp_dump.h"
28 #include "bgpd/bgp_filter.h"
29 #include "bgpd/bgp_route.h"
30 #include "bgpd/bgp_vty.h"
31 #include "bgpd/bgp_zebra.h"
34 #include "bgpd/rfapi/rfapi_backend.h"
37 /* Required variables to link in libbgp */
38 struct zebra_privs_t bgpd_privs
= {0};
39 struct thread_master
*master
= NULL
;
50 enum test_state state
;
58 struct peer_group
*group
;
64 const char *peer_address
;
65 const char *peer_group
;
68 struct test_peer_family
{
73 struct test_peer_attr
{
76 const char *group_cmd
;
78 enum { PEER_AT_AF_FLAG
= 0,
79 PEER_AT_AF_FILTER
= 1,
95 struct test_peer_family families
[AFI_MAX
* SAFI_MAX
];
98 #define OUT_SYMBOL_INFO "\u25ba"
99 #define OUT_SYMBOL_OK "\u2714"
100 #define OUT_SYMBOL_NOK "\u2716"
102 /* clang-format off */
103 #define TEST_ASSERT(T, C) \
105 if ((T)->state != TEST_SUCCESS || (C)) \
108 (T)->state = TEST_ASSERT_ERROR; \
109 (T)->error = str_printf("assertion failed: %s", (#C)); \
112 #define TEST_AF_FLAGS(T, P, A, V, O) \
114 if ((T)->state != TEST_SUCCESS) \
117 TEST_ASSERT((T), !!CHECK_FLAG((P)->af_flags[(A)->afi][(A)->safi], (A)->u.flag) == ((V) ^ (A)->o.invert)); \
118 TEST_ASSERT((T), !!CHECK_FLAG((P)->af_flags_override[(A)->afi][(A)->safi], (A)->u.flag) == (O)); \
119 TEST_ASSERT((T), !!CHECK_FLAG((P)->af_flags_invert[(A)->afi][(A)->safi], (A)->u.flag) == (A)->o.invert); \
122 #define TEST_AF_FILTER(T, P, A, S, O) \
124 if ((T)->state != TEST_SUCCESS) \
127 TEST_ASSERT((T), !!CHECK_FLAG((P)->filter_override[(A)->afi][(A)->safi][(A)->u.filter.direct], (A)->u.filter.flag) == (O)); \
128 switch ((A)->u.filter.flag) { \
129 case PEER_FT_DISTRIBUTE_LIST: \
130 TEST_ASSERT((T), !!((P)->filter[(A)->afi][(A)->safi].dlist[(A)->u.filter.direct].name) == (S)); \
132 case PEER_FT_FILTER_LIST: \
133 TEST_ASSERT((T), !!((P)->filter[(A)->afi][(A)->safi].aslist[(A)->u.filter.direct].name) == (S)); \
135 case PEER_FT_PREFIX_LIST: \
136 TEST_ASSERT((T), !!((P)->filter[(A)->afi][(A)->safi].plist[(A)->u.filter.direct].name) == (S)); \
138 case PEER_FT_ROUTE_MAP: \
139 TEST_ASSERT((T), !!((P)->filter[(A)->afi][(A)->safi].map[(A)->u.filter.direct].name) == (S)); \
141 case PEER_FT_UNSUPPRESS_MAP: \
142 TEST_ASSERT((T), !!((P)->filter[(A)->afi][(A)->safi].usmap.name) == (S)); \
146 /* clang-format on */
148 static struct test_config cfg
= {
151 .peer_address
= "1.1.1.1",
152 .peer_group
= "PG-TEST",
155 /* clang-format off */
156 static struct test_peer_attr test_peer_attrs
[] = {
158 .cmd
= "addpath-tx-all-paths",
159 .u
.flag
= PEER_FLAG_ADDPATH_TX_ALL_PATHS
,
161 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
162 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
166 .cmd
= "addpath-tx-bestpath-per-AS",
167 .u
.flag
= PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS
,
169 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
170 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
175 .peer_cmd
= "allowas-in 1",
176 .group_cmd
= "allowas-in 2",
177 .u
.flag
= PEER_FLAG_ALLOWAS_IN
,
179 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
180 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
184 .cmd
= "allowas-in origin",
185 .u
.flag
= PEER_FLAG_ALLOWAS_IN_ORIGIN
,
187 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
188 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
192 .cmd
= "as-override",
193 .u
.flag
= PEER_FLAG_AS_OVERRIDE
,
195 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
196 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
200 .cmd
= "attribute-unchanged as-path",
201 .u
.flag
= PEER_FLAG_AS_PATH_UNCHANGED
,
203 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
204 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
208 .cmd
= "attribute-unchanged next-hop",
209 .u
.flag
= PEER_FLAG_NEXTHOP_UNCHANGED
,
211 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
212 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
216 .cmd
= "attribute-unchanged med",
217 .u
.flag
= PEER_FLAG_MED_UNCHANGED
,
219 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
220 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
224 .cmd
= "attribute-unchanged as-path next-hop",
225 .u
.flag
= PEER_FLAG_AS_PATH_UNCHANGED
226 | PEER_FLAG_NEXTHOP_UNCHANGED
,
228 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
229 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
233 .cmd
= "attribute-unchanged as-path med",
234 .u
.flag
= PEER_FLAG_AS_PATH_UNCHANGED
235 | PEER_FLAG_MED_UNCHANGED
,
237 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
238 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
242 .cmd
= "attribute-unchanged as-path next-hop med",
243 .u
.flag
= PEER_FLAG_AS_PATH_UNCHANGED
244 | PEER_FLAG_NEXTHOP_UNCHANGED
245 | PEER_FLAG_MED_UNCHANGED
,
247 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
248 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
252 .cmd
= "capability orf prefix-list send",
253 .u
.flag
= PEER_FLAG_ORF_PREFIX_SM
,
255 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
256 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
260 .cmd
= "capability orf prefix-list receive",
261 .u
.flag
= PEER_FLAG_ORF_PREFIX_RM
,
263 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
264 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
268 .cmd
= "capability orf prefix-list both",
269 .u
.flag
= PEER_FLAG_ORF_PREFIX_SM
| PEER_FLAG_ORF_PREFIX_RM
,
271 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
272 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
276 .cmd
= "default-originate",
277 .u
.flag
= PEER_FLAG_DEFAULT_ORIGINATE
,
279 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
280 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
284 .cmd
= "default-originate route-map",
285 .peer_cmd
= "default-originate route-map RM-PEER",
286 .group_cmd
= "default-originate route-map RM-GROUP",
287 .u
.flag
= PEER_FLAG_DEFAULT_ORIGINATE
,
289 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
290 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
294 .cmd
= "distribute-list",
295 .peer_cmd
= "distribute-list DL-PEER in",
296 .group_cmd
= "distribute-list DL-GROUP in",
297 .type
= PEER_AT_AF_FILTER
,
298 .u
.filter
.flag
= PEER_FT_DISTRIBUTE_LIST
,
299 .u
.filter
.direct
= FILTER_IN
,
301 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
302 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
306 .cmd
= "distribute-list",
307 .peer_cmd
= "distribute-list DL-PEER out",
308 .group_cmd
= "distribute-list DL-GROUP out",
309 .type
= PEER_AT_AF_FILTER
,
310 .u
.filter
.flag
= PEER_FT_DISTRIBUTE_LIST
,
311 .u
.filter
.direct
= FILTER_OUT
,
313 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
314 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
318 .cmd
= "filter-list",
319 .peer_cmd
= "filter-list FL-PEER in",
320 .group_cmd
= "filter-list FL-GROUP in",
321 .type
= PEER_AT_AF_FILTER
,
322 .u
.filter
.flag
= PEER_FT_FILTER_LIST
,
323 .u
.filter
.direct
= FILTER_IN
,
325 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
326 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
330 .cmd
= "filter-list",
331 .peer_cmd
= "filter-list FL-PEER out",
332 .group_cmd
= "filter-list FL-GROUP out",
333 .type
= PEER_AT_AF_FILTER
,
334 .u
.filter
.flag
= PEER_FT_FILTER_LIST
,
335 .u
.filter
.direct
= FILTER_OUT
,
337 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
338 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
342 .cmd
= "maximum-prefix",
343 .peer_cmd
= "maximum-prefix 10",
344 .group_cmd
= "maximum-prefix 20",
345 .u
.flag
= PEER_FLAG_MAX_PREFIX
,
347 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
348 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
352 .cmd
= "maximum-prefix",
353 .peer_cmd
= "maximum-prefix 10 restart 100",
354 .group_cmd
= "maximum-prefix 20 restart 200",
355 .u
.flag
= PEER_FLAG_MAX_PREFIX
,
357 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
358 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
362 .cmd
= "maximum-prefix",
363 .peer_cmd
= "maximum-prefix 10 1 restart 100",
364 .group_cmd
= "maximum-prefix 20 2 restart 200",
365 .u
.flag
= PEER_FLAG_MAX_PREFIX
,
367 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
368 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
372 .cmd
= "maximum-prefix",
373 .peer_cmd
= "maximum-prefix 10 warning-only",
374 .group_cmd
= "maximum-prefix 20 warning-only",
375 .u
.flag
= PEER_FLAG_MAX_PREFIX
| PEER_FLAG_MAX_PREFIX_WARNING
,
377 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
378 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
382 .cmd
= "maximum-prefix",
383 .peer_cmd
= "maximum-prefix 10 1 warning-only",
384 .group_cmd
= "maximum-prefix 20 2 warning-only",
385 .u
.flag
= PEER_FLAG_MAX_PREFIX
| PEER_FLAG_MAX_PREFIX_WARNING
,
387 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
388 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
392 .cmd
= "next-hop-self",
393 .u
.flag
= PEER_FLAG_NEXTHOP_SELF
,
395 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
396 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
400 .cmd
= "next-hop-self force",
401 .u
.flag
= PEER_FLAG_FORCE_NEXTHOP_SELF
,
403 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
404 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
408 .cmd
= "prefix-list",
409 .peer_cmd
= "prefix-list PL-PEER in",
410 .group_cmd
= "prefix-list PL-GROUP in",
411 .type
= PEER_AT_AF_FILTER
,
412 .u
.filter
.flag
= PEER_FT_PREFIX_LIST
,
413 .u
.filter
.direct
= FILTER_IN
,
415 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
416 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
420 .cmd
= "prefix-list",
421 .peer_cmd
= "prefix-list PL-PEER out",
422 .group_cmd
= "prefix-list PL-GROUP out",
423 .type
= PEER_AT_AF_FILTER
,
424 .u
.filter
.flag
= PEER_FT_PREFIX_LIST
,
425 .u
.filter
.direct
= FILTER_OUT
,
427 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
428 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
432 .cmd
= "remove-private-AS",
433 .u
.flag
= PEER_FLAG_REMOVE_PRIVATE_AS
,
435 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
436 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
440 .cmd
= "remove-private-AS all",
441 .u
.flag
= PEER_FLAG_REMOVE_PRIVATE_AS
442 | PEER_FLAG_REMOVE_PRIVATE_AS_ALL
,
444 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
445 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
449 .cmd
= "remove-private-AS replace-AS",
450 .u
.flag
= PEER_FLAG_REMOVE_PRIVATE_AS
451 | PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
,
453 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
454 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
458 .cmd
= "remove-private-AS all replace-AS",
459 .u
.flag
= PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
,
461 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
462 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
467 .peer_cmd
= "route-map RM-PEER in",
468 .group_cmd
= "route-map RM-GROUP in",
469 .type
= PEER_AT_AF_FILTER
,
470 .u
.filter
.flag
= PEER_FT_ROUTE_MAP
,
471 .u
.filter
.direct
= FILTER_IN
,
473 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
474 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
479 .peer_cmd
= "route-map RM-PEER out",
480 .group_cmd
= "route-map RM-GROUP out",
481 .type
= PEER_AT_AF_FILTER
,
482 .u
.filter
.flag
= PEER_FT_ROUTE_MAP
,
483 .u
.filter
.direct
= FILTER_OUT
,
485 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
486 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
490 .cmd
= "route-reflector-client",
491 .u
.flag
= PEER_FLAG_REFLECTOR_CLIENT
,
494 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
495 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
499 .cmd
= "route-server-client",
500 .u
.flag
= PEER_FLAG_RSERVER_CLIENT
,
502 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
503 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
507 .cmd
= "send-community",
508 .u
.flag
= PEER_FLAG_SEND_COMMUNITY
,
511 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
512 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
516 .cmd
= "send-community extended",
517 .u
.flag
= PEER_FLAG_SEND_EXT_COMMUNITY
,
520 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
521 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
525 .cmd
= "send-community large",
526 .u
.flag
= PEER_FLAG_SEND_LARGE_COMMUNITY
,
529 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
530 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
534 .cmd
= "soft-reconfiguration inbound",
535 .u
.flag
= PEER_FLAG_SOFT_RECONFIG
,
537 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
538 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
542 .cmd
= "unsuppress-map",
543 .peer_cmd
= "unsuppress-map UM-PEER",
544 .group_cmd
= "unsuppress-map UM-GROUP",
545 .type
= PEER_AT_AF_FILTER
,
546 .u
.filter
.flag
= PEER_FT_UNSUPPRESS_MAP
,
547 .u
.filter
.direct
= 0,
549 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
550 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
555 .peer_cmd
= "weight 100",
556 .group_cmd
= "weight 200",
557 .u
.flag
= PEER_FLAG_WEIGHT
,
559 { .afi
= AFI_IP
, .safi
= SAFI_UNICAST
},
560 { .afi
= AFI_IP6
, .safi
= SAFI_UNICAST
},
565 /* clang-format on */
567 static char *str_vprintf(const char *fmt
, va_list ap
)
576 ret
= vsnprintf(buf
, buf_size
, fmt
, apc
);
579 if (ret
>= 0 && ret
< buf_size
)
587 buf
= XREALLOC(MTYPE_TMP
, buf
, buf_size
);
593 static char *str_printf(const char *fmt
, ...)
599 buf
= str_vprintf(fmt
, ap
);
605 static const char *str_from_afi(afi_t afi
)
613 return "<unknown AFI>";
617 static const char *str_from_safi(safi_t safi
)
625 return "labeled-unicast";
629 return "<unknown SAFI>";
633 static void test_execute(struct test
*test
, const char *fmt
, ...)
640 /* Skip execution if test instance has previously failed. */
641 if (test
->state
!= TEST_SUCCESS
)
644 /* Format command string with variadic arguments. */
646 cmd
= str_vprintf(fmt
, ap
);
649 test
->state
= TEST_INTERNAL_ERROR
;
651 str_printf("could not format command string [%s]", fmt
);
655 /* Tokenize formatted command string. */
656 vline
= cmd_make_strvec(cmd
);
658 test
->state
= TEST_INTERNAL_ERROR
;
659 test
->error
= str_printf(
660 "tokenizing command string [%s] returned empty result",
662 XFREE(MTYPE_TMP
, cmd
);
667 /* Execute command (non-strict). */
668 ret
= cmd_execute_command(vline
, test
->vty
, NULL
, 0);
669 if (ret
!= CMD_SUCCESS
) {
670 test
->state
= TEST_COMMAND_ERROR
;
671 test
->error
= str_printf(
672 "execution of command [%s] has failed with code [%d]",
676 /* Free memory and return. */
677 cmd_free_strvec(vline
);
678 XFREE(MTYPE_TMP
, cmd
);
682 static void test_config(struct test
*test
, const char *fmt
, bool invert
,
690 /* Skip execution if test instance has previously failed. */
691 if (test
->state
!= TEST_SUCCESS
)
694 /* Format matcher string with variadic arguments. */
696 matcher
= str_vprintf(fmt
, apc
);
699 test
->state
= TEST_INTERNAL_ERROR
;
701 str_printf("could not format matcher string [%s]", fmt
);
705 /* Fetch BGP configuration into buffer. */
706 bgp_config_write(test
->vty
);
707 config
= buffer_getstr(test
->vty
->obuf
);
708 buffer_reset(test
->vty
->obuf
);
710 /* Match config against matcher. */
711 matched
= !!strstr(config
, matcher
);
712 if (!matched
&& !invert
) {
713 test
->state
= TEST_CONFIG_ERROR
;
714 test
->error
= str_printf("expected config [%s] to be present",
716 } else if (matched
&& invert
) {
717 test
->state
= TEST_CONFIG_ERROR
;
718 test
->error
= str_printf("expected config [%s] to be absent",
722 /* Free memory and return. */
723 XFREE(MTYPE_TMP
, matcher
);
724 XFREE(MTYPE_TMP
, config
);
728 static void test_config_present(struct test
*test
, const char *fmt
, ...)
733 test_config(test
, fmt
, false, ap
);
737 static void test_config_absent(struct test
*test
, const char *fmt
, ...)
742 test_config(test
, fmt
, true, ap
);
746 static struct test
*test_new(const char *desc
, bool use_ibgp
)
751 test
= XCALLOC(MTYPE_TMP
, sizeof(struct test
));
752 test
->state
= TEST_SUCCESS
;
753 test
->desc
= XSTRDUP(MTYPE_TMP
, desc
);
754 test
->log
= list_new();
756 test
->vty
= vty_new();
757 test
->vty
->type
= VTY_TERM
;
758 test
->vty
->node
= CONFIG_NODE
;
760 /* Attempt gracefully to purge previous BGP configuration. */
761 test_execute(test
, "no router bgp");
762 test
->state
= TEST_SUCCESS
;
764 /* Initialize BGP test environment. */
765 test_execute(test
, "router bgp %d", cfg
.local_asn
);
766 test_execute(test
, "no bgp default ipv4-unicast");
767 test_execute(test
, "neighbor %s peer-group", cfg
.peer_group
);
768 test_execute(test
, "neighbor %s remote-as %d", cfg
.peer_address
,
769 use_ibgp
? cfg
.local_asn
: cfg
.peer_asn
);
770 if (test
->state
!= TEST_SUCCESS
)
773 /* Fetch default BGP instance. */
774 test
->bgp
= bgp_get_default();
776 test
->state
= TEST_INTERNAL_ERROR
;
778 str_printf("could not retrieve default bgp instance");
782 /* Fetch peer instance. */
783 str2sockunion(cfg
.peer_address
, &su
);
784 test
->peer
= peer_lookup(test
->bgp
, &su
);
786 test
->state
= TEST_INTERNAL_ERROR
;
787 test
->error
= str_printf(
788 "could not retrieve instance of bgp peer [%s]",
793 /* Fetch peer-group instance. */
794 test
->group
= peer_group_lookup(test
->bgp
, cfg
.peer_group
);
796 test
->state
= TEST_INTERNAL_ERROR
;
797 test
->error
= str_printf(
798 "could not retrieve instance of bgp peer-group [%s]",
806 static void test_log(struct test
*test
, const char *fmt
, ...)
810 /* Skip logging if test instance has previously failed. */
811 if (test
->state
!= TEST_SUCCESS
)
814 /* Store formatted log message. */
816 listnode_add(test
->log
, str_vprintf(fmt
, ap
));
820 static void test_finish(struct test
*test
)
823 struct listnode
*node
, *nnode
;
825 /* Print test output header. */
826 printf("%s [test] %s\n",
827 (test
->state
== TEST_SUCCESS
) ? OUT_SYMBOL_OK
: OUT_SYMBOL_NOK
,
830 /* Print test log messages. */
831 for (ALL_LIST_ELEMENTS(test
->log
, node
, nnode
, msg
)) {
832 printf("%s %s\n", OUT_SYMBOL_INFO
, msg
);
833 XFREE(MTYPE_TMP
, msg
);
836 /* Print test error message if available. */
837 if (test
->state
!= TEST_SUCCESS
&& test
->error
)
838 printf("%s error: %s\n", OUT_SYMBOL_INFO
, test
->error
);
840 /* Print machine-readable result of test. */
841 printf("%s\n", test
->state
== TEST_SUCCESS
? "OK" : "failed");
843 /* Cleanup allocated memory. */
845 vty_close(test
->vty
);
849 list_delete_and_null(&test
->log
);
851 XFREE(MTYPE_TMP
, test
->desc
);
853 XFREE(MTYPE_TMP
, test
->error
);
854 XFREE(MTYPE_TMP
, test
);
857 static void test_peer_attr(struct test
*test
, struct test_peer_attr
*pa
)
860 const char *ec
= pa
->o
.invert
? "no " : "";
861 const char *dc
= pa
->o
.invert
? "" : "no ";
862 const char *peer_cmd
= pa
->peer_cmd
?: pa
->cmd
;
863 const char *group_cmd
= pa
->group_cmd
?: pa
->cmd
;
864 struct peer
*p
= test
->peer
;
865 struct peer_group
*g
= test
->group
;
867 /* Test Case: Switch active address-family. */
868 if (pa
->type
== PEER_AT_AF_FLAG
|| pa
->type
== PEER_AT_AF_FILTER
) {
869 test_log(test
, "prepare: switch address-family to [%s]",
870 afi_safi_print(pa
->afi
, pa
->safi
));
871 test_execute(test
, "address-family %s %s",
872 str_from_afi(pa
->afi
), str_from_safi(pa
->safi
));
875 /* Test Case: Set flag on BGP peer. */
876 test_log(test
, "case %02d: set af-flag [%s] on [%s]", tc
++, peer_cmd
,
878 test_execute(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
879 test_config_present(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
880 test_config_absent(test
, "neighbor %s %s", g
->name
, pa
->cmd
);
881 if (pa
->type
== PEER_AT_AF_FLAG
) {
882 TEST_AF_FLAGS(test
, p
, pa
, true, true);
883 TEST_AF_FLAGS(test
, g
->conf
, pa
, false, false);
884 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
885 TEST_AF_FILTER(test
, p
, pa
, true, true);
886 TEST_AF_FILTER(test
, g
->conf
, pa
, false, false);
889 /* Test Case: Add BGP peer to peer-group. */
890 test_log(test
, "case %02d: add peer [%s] to group [%s]", tc
++, p
->host
,
892 test_execute(test
, "neighbor %s peer-group %s", p
->host
, g
->name
);
893 test_config_present(test
, "neighbor %s peer-group %s", p
->host
,
895 test_config_present(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
896 test_config_absent(test
, "neighbor %s %s", g
->name
, pa
->cmd
);
897 if (pa
->type
== PEER_AT_AF_FLAG
) {
898 TEST_AF_FLAGS(test
, p
, pa
, true, true);
899 TEST_AF_FLAGS(test
, g
->conf
, pa
, false, false);
900 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
901 TEST_AF_FILTER(test
, p
, pa
, true, true);
902 TEST_AF_FILTER(test
, g
->conf
, pa
, false, false);
905 /* Test Case: Re-add BGP peer to peer-group. */
906 test_log(test
, "case %02d: re-add peer [%s] to group [%s]", tc
++,
908 test_execute(test
, "neighbor %s peer-group %s", p
->host
, g
->name
);
909 test_config_present(test
, "neighbor %s peer-group %s", p
->host
,
911 test_config_present(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
912 test_config_absent(test
, "neighbor %s %s", g
->name
, pa
->cmd
);
913 if (pa
->type
== PEER_AT_AF_FLAG
) {
914 TEST_AF_FLAGS(test
, p
, pa
, true, true);
915 TEST_AF_FLAGS(test
, g
->conf
, pa
, false, false);
916 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
917 TEST_AF_FILTER(test
, p
, pa
, true, true);
918 TEST_AF_FILTER(test
, g
->conf
, pa
, false, false);
921 /* Test Case: Set flag on BGP peer-group. */
922 test_log(test
, "case %02d: set af-flag [%s] on [%s]", tc
++, group_cmd
,
924 test_execute(test
, "%sneighbor %s %s", ec
, g
->name
, group_cmd
);
925 test_config_present(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
926 test_config_present(test
, "%sneighbor %s %s", ec
, g
->name
, group_cmd
);
927 if (pa
->type
== PEER_AT_AF_FLAG
) {
928 TEST_AF_FLAGS(test
, p
, pa
, true, true);
929 TEST_AF_FLAGS(test
, g
->conf
, pa
, true, false);
930 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
931 TEST_AF_FILTER(test
, p
, pa
, true, true);
932 TEST_AF_FILTER(test
, g
->conf
, pa
, true, false);
935 /* Test Case: Unset flag on BGP peer-group. */
936 test_log(test
, "case %02d: unset af-flag [%s] on [%s]", tc
++, group_cmd
,
938 test_execute(test
, "%sneighbor %s %s", dc
, g
->name
, group_cmd
);
939 test_config_present(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
940 test_config_absent(test
, "neighbor %s %s", g
->name
, pa
->cmd
);
941 if (pa
->type
== PEER_AT_AF_FLAG
) {
942 TEST_AF_FLAGS(test
, p
, pa
, true, true);
943 TEST_AF_FLAGS(test
, g
->conf
, pa
, false, false);
944 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
945 TEST_AF_FILTER(test
, p
, pa
, true, true);
946 TEST_AF_FILTER(test
, g
->conf
, pa
, false, false);
949 /* Test Case: Set flag on BGP peer-group. */
950 test_log(test
, "case %02d: set af-flag [%s] on [%s]", tc
++, group_cmd
,
952 test_execute(test
, "%sneighbor %s %s", ec
, g
->name
, group_cmd
);
953 test_config_present(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
954 test_config_present(test
, "%sneighbor %s %s", ec
, g
->name
, group_cmd
);
955 if (pa
->type
== PEER_AT_AF_FLAG
) {
956 TEST_AF_FLAGS(test
, p
, pa
, true, true);
957 TEST_AF_FLAGS(test
, g
->conf
, pa
, true, false);
958 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
959 TEST_AF_FILTER(test
, p
, pa
, true, true);
960 TEST_AF_FILTER(test
, g
->conf
, pa
, true, false);
963 /* Test Case: Re-set flag on BGP peer. */
964 test_log(test
, "case %02d: re-set af-flag [%s] on [%s]", tc
++, peer_cmd
,
966 test_execute(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
967 test_config_present(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
968 test_config_present(test
, "%sneighbor %s %s", ec
, g
->name
, group_cmd
);
969 if (pa
->type
== PEER_AT_AF_FLAG
) {
970 TEST_AF_FLAGS(test
, p
, pa
, true, true);
971 TEST_AF_FLAGS(test
, g
->conf
, pa
, true, false);
972 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
973 TEST_AF_FILTER(test
, p
, pa
, true, true);
974 TEST_AF_FILTER(test
, g
->conf
, pa
, true, false);
977 /* Test Case: Unset flag on BGP peer. */
978 test_log(test
, "case %02d: unset af-flag [%s] on [%s]", tc
++, peer_cmd
,
980 test_execute(test
, "%sneighbor %s %s", dc
, p
->host
, peer_cmd
);
981 test_config_absent(test
, "neighbor %s %s", p
->host
, pa
->cmd
);
982 test_config_present(test
, "%sneighbor %s %s", ec
, g
->name
, group_cmd
);
983 if (pa
->type
== PEER_AT_AF_FLAG
) {
984 TEST_AF_FLAGS(test
, p
, pa
, true, false);
985 TEST_AF_FLAGS(test
, g
->conf
, pa
, true, false);
986 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
987 TEST_AF_FILTER(test
, p
, pa
, true, false);
988 TEST_AF_FILTER(test
, g
->conf
, pa
, true, false);
991 /* Test Case: Unset flag on BGP peer-group. */
992 test_log(test
, "case %02d: unset af-flag [%s] on [%s]", tc
++, group_cmd
,
994 test_execute(test
, "%sneighbor %s %s", dc
, g
->name
, group_cmd
);
995 test_config_absent(test
, "neighbor %s %s", p
->host
, pa
->cmd
);
996 test_config_absent(test
, "neighbor %s %s", g
->name
, pa
->cmd
);
997 if (pa
->type
== PEER_AT_AF_FLAG
) {
998 TEST_AF_FLAGS(test
, p
, pa
, false, false);
999 TEST_AF_FLAGS(test
, g
->conf
, pa
, false, false);
1000 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
1001 TEST_AF_FILTER(test
, p
, pa
, false, false);
1002 TEST_AF_FILTER(test
, g
->conf
, pa
, false, false);
1005 /* Test Case: Set flag on BGP peer. */
1006 test_log(test
, "case %02d: set af-flag [%s] on [%s]", tc
++, peer_cmd
,
1008 test_execute(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
1009 test_config_present(test
, "%sneighbor %s %s", ec
, p
->host
, peer_cmd
);
1010 test_config_absent(test
, "neighbor %s %s", g
->name
, pa
->cmd
);
1011 if (pa
->type
== PEER_AT_AF_FLAG
) {
1012 TEST_AF_FLAGS(test
, p
, pa
, true, true);
1013 TEST_AF_FLAGS(test
, g
->conf
, pa
, false, false);
1014 } else if (pa
->type
== PEER_AT_AF_FILTER
) {
1015 TEST_AF_FILTER(test
, p
, pa
, true, true);
1016 TEST_AF_FILTER(test
, g
->conf
, pa
, false, false);
1020 static void bgp_startup()
1023 openzlog("testbgpd", "NONE", 0, LOG_CONS
| LOG_NDELAY
| LOG_PID
,
1025 zprivs_preinit(&bgpd_privs
);
1026 zprivs_init(&bgpd_privs
);
1028 master
= thread_master_create(NULL
);
1029 bgp_master_init(master
);
1030 bgp_option_set(BGP_OPT_NO_LISTEN
);
1031 vrf_init(NULL
, NULL
, NULL
, NULL
);
1036 static void bgp_shutdown()
1039 struct listnode
*node
, *nnode
;
1043 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
1047 bgp_route_map_terminate();
1049 bgp_pthreads_finish();
1050 access_list_add_hook(NULL
);
1051 access_list_delete_hook(NULL
);
1052 access_list_reset();
1053 as_list_add_hook(NULL
);
1054 as_list_delete_hook(NULL
);
1056 prefix_list_add_hook(NULL
);
1057 prefix_list_delete_hook(NULL
);
1058 prefix_list_reset();
1059 community_list_terminate(bgp_clist
);
1061 #ifdef ENABLE_BGP_VNC
1062 vnc_zebra_destroy();
1064 bgp_zebra_destroy();
1066 bf_free(bm
->rd_idspace
);
1067 list_delete_and_null(&bm
->bgp
);
1068 memset(bm
, 0, sizeof(*bm
));
1072 zprivs_terminate(&bgpd_privs
);
1073 thread_master_free(master
);
1081 struct list
*pa_list
;
1082 struct test_peer_attr
*pa
, *pac
;
1083 struct listnode
*node
, *nnode
;
1087 pa_list
= list_new();
1089 while (test_peer_attrs
[i
].cmd
) {
1090 pa
= &test_peer_attrs
[i
++];
1092 if (pa
->families
[0].afi
&& pa
->families
[0].safi
) {
1095 while (pa
->families
[ii
].afi
&& pa
->families
[ii
].safi
) {
1096 pac
= XMALLOC(MTYPE_TMP
,
1097 sizeof(struct test_peer_attr
));
1098 memcpy(pac
, pa
, sizeof(struct test_peer_attr
));
1100 pac
->afi
= pa
->families
[ii
].afi
;
1101 pac
->safi
= pa
->families
[ii
].safi
;
1102 listnode_add(pa_list
, pac
);
1107 pac
= XMALLOC(MTYPE_TMP
, sizeof(struct test_peer_attr
));
1108 memcpy(pac
, pa
, sizeof(struct test_peer_attr
));
1109 listnode_add(pa_list
, pac
);
1113 for (ALL_LIST_ELEMENTS(pa_list
, node
, nnode
, pa
)) {
1117 /* Build test description string. */
1118 if (pa
->afi
&& pa
->safi
)
1119 desc
= str_printf("peer\\%s-%s\\%s",
1120 str_from_afi(pa
->afi
),
1121 str_from_safi(pa
->safi
), pa
->cmd
);
1123 desc
= str_printf("peer\\%s", pa
->cmd
);
1125 /* Initialize new test instance. */
1126 test
= test_new(desc
, pa
->o
.use_ibgp
);
1127 XFREE(MTYPE_TMP
, desc
);
1129 /* Execute tests and finish test instance. */
1130 test_peer_attr(test
, pa
);
1133 /* Print empty line as spacer. */
1136 /* Free memory used for peer-attr declaration. */
1137 XFREE(MTYPE_TMP
, pa
);
1140 list_delete_and_null(&pa_list
);