bgpd: Fix AF-attribute overrides when binding peer

The current implementation of the overrides for peer address-family
attributes suffered a bug, which caused all peer-specific attributes to
be lost when the peer was added to a peer-group which already had that
specific address-family active.

This commit extends the *peer_group2peer_config_copy_af* function to
respect overridden flags properly. Additionally, the arguments of the
macros *PEER_ATTR_INHERIT* and *PEER_STR_ATTR_INHERIT* have been
reordered to be more consistent and easy to read.

This commit also adds further test cases to the BGP peer attributes test
suite, so that this kind of error is being caught in future commits. The
missing AF-attribute *distribute-list* has also been added to the test
suite.

Signed-off-by: Pascal Mathis <mail@pascalmathis.com>
This commit is contained in:
Pascal Mathis 2018-06-12 17:09:49 +02:00
parent 9fb964de21
commit e7103a9644
No known key found for this signature in database
GPG Key ID: E208DBA7BFC9B28C
4 changed files with 247 additions and 149 deletions

View File

@ -1813,141 +1813,111 @@ static void peer_group2peer_config_copy_af(struct peer_group *group,
{ {
int in = FILTER_IN; int in = FILTER_IN;
int out = FILTER_OUT; int out = FILTER_OUT;
uint32_t pflags_ovrd;
uint8_t *pfilter_ovrd;
struct peer *conf; struct peer *conf;
struct bgp_filter *pfilter;
struct bgp_filter *gfilter;
conf = group->conf; conf = group->conf;
pfilter = &peer->filter[afi][safi]; pflags_ovrd = peer->af_flags_override[afi][safi];
gfilter = &conf->filter[afi][safi]; pfilter_ovrd = &peer->filter_override[afi][safi][in];
/* peer af_flags apply */ /* peer af_flags apply */
peer->af_flags[afi][safi] = conf->af_flags[afi][safi]; peer->af_flags[afi][safi] |= conf->af_flags[afi][safi] & ~pflags_ovrd;
peer->af_flags_invert[afi][safi] = conf->af_flags_invert[afi][safi]; peer->af_flags_invert[afi][safi] |= conf->af_flags_invert[afi][safi];
/* maximum-prefix */ /* maximum-prefix */
peer->pmax[afi][safi] = conf->pmax[afi][safi]; if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_MAX_PREFIX)) {
peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi]; PEER_ATTR_INHERIT(peer, group, pmax[afi][safi]);
peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi]; PEER_ATTR_INHERIT(peer, group, pmax_threshold[afi][safi]);
PEER_ATTR_INHERIT(peer, group, pmax_restart[afi][safi]);
}
/* allowas-in */ /* allowas-in */
peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi]; if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_ALLOWAS_IN))
PEER_ATTR_INHERIT(peer, group, allowas_in[afi][safi]);
/* weight */ /* weight */
peer->weight[afi][safi] = conf->weight[afi][safi]; if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_WEIGHT))
PEER_ATTR_INHERIT(peer, group, weight[afi][safi]);
/* default-originate route-map */ /* default-originate route-map */
if (conf->default_rmap[afi][safi].name) { if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_DEFAULT_ORIGINATE)) {
if (peer->default_rmap[afi][safi].name) PEER_STR_ATTR_INHERIT(peer, group, default_rmap[afi][safi].name,
XFREE(MTYPE_BGP_FILTER_NAME, MTYPE_ROUTE_MAP_NAME);
peer->default_rmap[afi][safi].name); PEER_ATTR_INHERIT(peer, group, default_rmap[afi][safi].map);
peer->default_rmap[afi][safi].name =
XSTRDUP(MTYPE_BGP_FILTER_NAME,
conf->default_rmap[afi][safi].name);
peer->default_rmap[afi][safi].map =
conf->default_rmap[afi][safi].map;
} }
/* inbound filter apply */ /* inbound filter apply */
if (gfilter->dlist[in].name && !pfilter->dlist[in].name) { if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_DISTRIBUTE_LIST)) {
if (pfilter->dlist[in].name) PEER_STR_ATTR_INHERIT(peer, group,
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[in].name); filter[afi][safi].dlist[in].name,
pfilter->dlist[in].name = MTYPE_BGP_FILTER_NAME);
XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[in].name); PEER_ATTR_INHERIT(peer, group,
pfilter->dlist[in].alist = gfilter->dlist[in].alist; filter[afi][safi].dlist[in].alist);
} }
if (gfilter->plist[in].name && !pfilter->plist[in].name) { if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_PREFIX_LIST)) {
if (pfilter->plist[in].name) PEER_STR_ATTR_INHERIT(peer, group,
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[in].name); filter[afi][safi].plist[in].name,
pfilter->plist[in].name = MTYPE_BGP_FILTER_NAME);
XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[in].name); PEER_ATTR_INHERIT(peer, group,
pfilter->plist[in].plist = gfilter->plist[in].plist; filter[afi][safi].plist[in].plist);
} }
if (gfilter->aslist[in].name && !pfilter->aslist[in].name) { if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_FILTER_LIST)) {
if (pfilter->aslist[in].name) PEER_STR_ATTR_INHERIT(peer, group,
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[in].name); filter[afi][safi].aslist[in].name,
pfilter->aslist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, MTYPE_BGP_FILTER_NAME);
gfilter->aslist[in].name); PEER_ATTR_INHERIT(peer, group,
pfilter->aslist[in].aslist = gfilter->aslist[in].aslist; filter[afi][safi].aslist[in].aslist);
} }
if (gfilter->map[RMAP_IN].name && !pfilter->map[RMAP_IN].name) { if (!CHECK_FLAG(pfilter_ovrd[RMAP_IN], PEER_FT_ROUTE_MAP)) {
if (pfilter->map[RMAP_IN].name) PEER_STR_ATTR_INHERIT(peer, group,
XFREE(MTYPE_BGP_FILTER_NAME, filter[afi][safi].map[in].name,
pfilter->map[RMAP_IN].name); MTYPE_BGP_FILTER_NAME);
pfilter->map[RMAP_IN].name = XSTRDUP( PEER_ATTR_INHERIT(peer, group,
MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_IN].name); filter[afi][safi].map[RMAP_IN].map);
pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
} }
/* outbound filter apply */ /* outbound filter apply */
if (gfilter->dlist[out].name) { if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_DISTRIBUTE_LIST)) {
if (pfilter->dlist[out].name) PEER_STR_ATTR_INHERIT(peer, group,
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name); filter[afi][safi].dlist[out].name,
pfilter->dlist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, MTYPE_BGP_FILTER_NAME);
gfilter->dlist[out].name); PEER_ATTR_INHERIT(peer, group,
pfilter->dlist[out].alist = gfilter->dlist[out].alist; filter[afi][safi].dlist[out].alist);
} else {
if (pfilter->dlist[out].name)
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name);
pfilter->dlist[out].name = NULL;
pfilter->dlist[out].alist = NULL;
} }
if (gfilter->plist[out].name) { if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_PREFIX_LIST)) {
if (pfilter->plist[out].name) PEER_STR_ATTR_INHERIT(peer, group,
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name); filter[afi][safi].plist[out].name,
pfilter->plist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, MTYPE_BGP_FILTER_NAME);
gfilter->plist[out].name); PEER_ATTR_INHERIT(peer, group,
pfilter->plist[out].plist = gfilter->plist[out].plist; filter[afi][safi].plist[out].plist);
} else {
if (pfilter->plist[out].name)
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name);
pfilter->plist[out].name = NULL;
pfilter->plist[out].plist = NULL;
} }
if (gfilter->aslist[out].name) { if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_FILTER_LIST)) {
if (pfilter->aslist[out].name) PEER_STR_ATTR_INHERIT(peer, group,
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name); filter[afi][safi].aslist[out].name,
pfilter->aslist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, MTYPE_BGP_FILTER_NAME);
gfilter->aslist[out].name); PEER_ATTR_INHERIT(peer, group,
pfilter->aslist[out].aslist = gfilter->aslist[out].aslist; filter[afi][safi].aslist[out].aslist);
} else {
if (pfilter->aslist[out].name)
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name);
pfilter->aslist[out].name = NULL;
pfilter->aslist[out].aslist = NULL;
} }
if (gfilter->map[RMAP_OUT].name) { if (!CHECK_FLAG(pfilter_ovrd[RMAP_OUT], PEER_FT_ROUTE_MAP)) {
if (pfilter->map[RMAP_OUT].name) PEER_STR_ATTR_INHERIT(peer, group,
XFREE(MTYPE_BGP_FILTER_NAME, filter[afi][safi].map[RMAP_OUT].name,
pfilter->map[RMAP_OUT].name); MTYPE_BGP_FILTER_NAME);
pfilter->map[RMAP_OUT].name = XSTRDUP( PEER_ATTR_INHERIT(peer, group,
MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_OUT].name); filter[afi][safi].map[RMAP_OUT].map);
pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
} else {
if (pfilter->map[RMAP_OUT].name)
XFREE(MTYPE_BGP_FILTER_NAME,
pfilter->map[RMAP_OUT].name);
pfilter->map[RMAP_OUT].name = NULL;
pfilter->map[RMAP_OUT].map = NULL;
} }
if (gfilter->usmap.name) { /* nondirectional filter apply */
if (pfilter->usmap.name) if (!CHECK_FLAG(pfilter_ovrd[0], PEER_FT_UNSUPPRESS_MAP)) {
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name); PEER_STR_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.name,
pfilter->usmap.name = MTYPE_BGP_FILTER_NAME);
XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->usmap.name); PEER_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.map);
pfilter->usmap.map = gfilter->usmap.map;
} else {
if (pfilter->usmap.name)
XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name);
pfilter->usmap.name = NULL;
pfilter->usmap.map = NULL;
} }
} }
@ -4766,9 +4736,11 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
if (peer_group_active(peer)) { if (peer_group_active(peer)) {
peer_af_flag_inherit(peer, afi, safi, peer_af_flag_inherit(peer, afi, safi,
PEER_FLAG_DEFAULT_ORIGINATE); PEER_FLAG_DEFAULT_ORIGINATE);
PEER_STR_ATTR_INHERIT(MTYPE_ROUTE_MAP_NAME, peer, PEER_STR_ATTR_INHERIT(peer, peer->group,
default_rmap[afi][safi].name); default_rmap[afi][safi].name,
PEER_ATTR_INHERIT(peer, default_rmap[afi][safi].map); MTYPE_ROUTE_MAP_NAME);
PEER_ATTR_INHERIT(peer, peer->group,
default_rmap[afi][safi].map);
} else { } else {
/* Otherwise remove flag and configuration from peer. */ /* Otherwise remove flag and configuration from peer. */
peer_af_flag_unset(peer, afi, safi, peer_af_flag_unset(peer, afi, safi,
@ -4910,7 +4882,7 @@ int peer_weight_unset(struct peer *peer, afi_t afi, safi_t safi)
/* Inherit configuration from peer-group if peer is member. */ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) { if (peer_group_active(peer)) {
peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_WEIGHT); peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_WEIGHT);
PEER_ATTR_INHERIT(peer, weight[afi][safi]); PEER_ATTR_INHERIT(peer, peer->group, weight[afi][safi]);
peer_on_policy_change(peer, afi, safi, 0); peer_on_policy_change(peer, afi, safi, 0);
return 0; return 0;
@ -5256,7 +5228,7 @@ int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)
peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_ALLOWAS_IN); peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
peer_af_flag_inherit(peer, afi, safi, peer_af_flag_inherit(peer, afi, safi,
PEER_FLAG_ALLOWAS_IN_ORIGIN); PEER_FLAG_ALLOWAS_IN_ORIGIN);
PEER_ATTR_INHERIT(peer, allowas_in[afi][safi]); PEER_ATTR_INHERIT(peer, peer->group, allowas_in[afi][safi]);
peer_on_policy_change(peer, afi, safi, 0); peer_on_policy_change(peer, afi, safi, 0);
return 0; return 0;
@ -5590,9 +5562,11 @@ int peer_distribute_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
/* Inherit configuration from peer-group if peer is member. */ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) { if (peer_group_active(peer)) {
PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer, PEER_STR_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].dlist[direct].name); filter[afi][safi].dlist[direct].name,
PEER_ATTR_INHERIT(peer, filter[afi][safi].dlist[direct].alist); MTYPE_BGP_FILTER_NAME);
PEER_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].dlist[direct].alist);
} else { } else {
/* Otherwise remove configuration from peer. */ /* Otherwise remove configuration from peer. */
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
@ -5773,9 +5747,11 @@ int peer_prefix_list_unset(struct peer *peer, afi_t afi, safi_t safi,
/* Inherit configuration from peer-group if peer is member. */ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) { if (peer_group_active(peer)) {
PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer, PEER_STR_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].plist[direct].name); filter[afi][safi].plist[direct].name,
PEER_ATTR_INHERIT(peer, filter[afi][safi].plist[direct].plist); MTYPE_BGP_FILTER_NAME);
PEER_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].plist[direct].plist);
} else { } else {
/* Otherwise remove configuration from peer. */ /* Otherwise remove configuration from peer. */
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
@ -5954,9 +5930,10 @@ int peer_aslist_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
/* Inherit configuration from peer-group if peer is member. */ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) { if (peer_group_active(peer)) {
PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer, PEER_STR_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].aslist[direct].name); filter[afi][safi].aslist[direct].name,
PEER_ATTR_INHERIT(peer, MTYPE_BGP_FILTER_NAME);
PEER_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].aslist[direct].aslist); filter[afi][safi].aslist[direct].aslist);
} else { } else {
/* Otherwise remove configuration from peer. */ /* Otherwise remove configuration from peer. */
@ -6139,9 +6116,11 @@ int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
/* Inherit configuration from peer-group if peer is member. */ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) { if (peer_group_active(peer)) {
PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer, PEER_STR_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].map[direct].name); filter[afi][safi].map[direct].name,
PEER_ATTR_INHERIT(peer, filter[afi][safi].map[direct].map); MTYPE_BGP_FILTER_NAME);
PEER_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].map[direct].map);
} else { } else {
/* Otherwise remove configuration from peer. */ /* Otherwise remove configuration from peer. */
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
@ -6248,9 +6227,11 @@ int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
/* Inherit configuration from peer-group if peer is member. */ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) { if (peer_group_active(peer)) {
PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer, PEER_STR_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].usmap.name); filter[afi][safi].usmap.name,
PEER_ATTR_INHERIT(peer, filter[afi][safi].usmap.map); MTYPE_BGP_FILTER_NAME);
PEER_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].usmap.map);
} else { } else {
/* Otherwise remove configuration from peer. */ /* Otherwise remove configuration from peer. */
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
@ -6361,9 +6342,9 @@ int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX); peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
peer_af_flag_inherit(peer, afi, safi, peer_af_flag_inherit(peer, afi, safi,
PEER_FLAG_MAX_PREFIX_WARNING); PEER_FLAG_MAX_PREFIX_WARNING);
PEER_ATTR_INHERIT(peer, pmax[afi][safi]); PEER_ATTR_INHERIT(peer, peer->group, pmax[afi][safi]);
PEER_ATTR_INHERIT(peer, pmax_threshold[afi][safi]); PEER_ATTR_INHERIT(peer, peer->group, pmax_threshold[afi][safi]);
PEER_ATTR_INHERIT(peer, pmax_restart[afi][safi]); PEER_ATTR_INHERIT(peer, peer->group, pmax_restart[afi][safi]);
return 0; return 0;
} }

View File

@ -1184,13 +1184,14 @@ struct peer {
DECLARE_QOBJ_TYPE(peer) DECLARE_QOBJ_TYPE(peer)
/* Inherit peer attribute from peer-group. */ /* Inherit peer attribute from peer-group. */
#define PEER_ATTR_INHERIT(peer, attr) ((peer)->attr = (peer)->group->conf->attr) #define PEER_ATTR_INHERIT(peer, group, attr) \
#define PEER_STR_ATTR_INHERIT(mt, peer, attr) \ ((peer)->attr = (group)->conf->attr)
#define PEER_STR_ATTR_INHERIT(peer, group, attr, mt) \
do { \ do { \
if ((peer)->attr) \ if ((peer)->attr) \
XFREE(mt, (peer)->attr); \ XFREE(mt, (peer)->attr); \
if ((peer)->group->conf->attr) \ if ((group)->conf->attr) \
(peer)->attr = XSTRDUP(mt, (peer)->group->conf->attr); \ (peer)->attr = XSTRDUP(mt, (group)->conf->attr); \
else \ else \
(peer)->attr = NULL; \ (peer)->attr = NULL; \
} while (0) } while (0)

View File

@ -56,6 +56,11 @@ struct test {
struct bgp *bgp; struct bgp *bgp;
struct peer *peer; struct peer *peer;
struct peer_group *group; struct peer_group *group;
struct {
bool use_ibgp;
bool use_iface_peer;
} o;
}; };
struct test_config { struct test_config {
@ -256,6 +261,22 @@ static struct test_peer_attr test_peer_attrs[] = {
.group_cmd = "default-originate route-map RM-GROUP", .group_cmd = "default-originate route-map RM-GROUP",
.u.flag = PEER_FLAG_DEFAULT_ORIGINATE, .u.flag = PEER_FLAG_DEFAULT_ORIGINATE,
}, },
{
.cmd = "distribute-list",
.peer_cmd = "distribute-list FL-PEER in",
.group_cmd = "distribute-list FL-GROUP in",
.type = PEER_AT_AF_FILTER,
.u.filter.flag = PEER_FT_DISTRIBUTE_LIST,
.u.filter.direct = FILTER_IN,
},
{
.cmd = "distribute-list",
.peer_cmd = "distribute-list FL-PEER out",
.group_cmd = "distribute-list FL-GROUP out",
.type = PEER_AT_AF_FILTER,
.u.filter.flag = PEER_FT_DISTRIBUTE_LIST,
.u.filter.direct = FILTER_OUT,
},
{ {
.cmd = "filter-list", .cmd = "filter-list",
.peer_cmd = "filter-list FL-PEER in", .peer_cmd = "filter-list FL-PEER in",
@ -596,20 +617,13 @@ static void test_config_absent(struct test *test, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
static struct test *test_new(const char *desc, bool use_ibgp, static void test_initialize(struct test *test)
bool use_iface_peer)
{ {
struct test *test;
union sockunion su; union sockunion su;
test = XCALLOC(MTYPE_TMP, sizeof(struct test)); /* Log message about (re)-initialization */
test->state = TEST_SUCCESS; test_log(test, "prepare: %sinitialize bgp test environment",
test->desc = XSTRDUP(MTYPE_TMP, desc); test->bgp ? "re-" : "");
test->log = list_new();
test->vty = vty_new();
test->vty->type = VTY_TERM;
test->vty->node = CONFIG_NODE;
/* Attempt gracefully to purge previous BGP configuration. */ /* Attempt gracefully to purge previous BGP configuration. */
test_execute(test, "no router bgp"); test_execute(test, "no router bgp");
@ -619,18 +633,18 @@ static struct test *test_new(const char *desc, bool use_ibgp,
test_execute(test, "router bgp %d", cfg.local_asn); test_execute(test, "router bgp %d", cfg.local_asn);
test_execute(test, "no bgp default ipv4-unicast"); test_execute(test, "no bgp default ipv4-unicast");
test_execute(test, "neighbor %s peer-group", cfg.peer_group); test_execute(test, "neighbor %s peer-group", cfg.peer_group);
if (use_iface_peer) { if (test->o.use_iface_peer) {
test_execute(test, "neighbor %s interface", cfg.peer_interface); test_execute(test, "neighbor %s interface", cfg.peer_interface);
test_execute(test, "neighbor %s remote-as %d", test_execute(test, "neighbor %s remote-as %d",
cfg.peer_interface, cfg.peer_interface,
use_ibgp ? cfg.local_asn : cfg.peer_asn); test->o.use_ibgp ? cfg.local_asn : cfg.peer_asn);
} else { } else {
test_execute(test, "neighbor %s remote-as %d", cfg.peer_address, test_execute(test, "neighbor %s remote-as %d", cfg.peer_address,
use_ibgp ? cfg.local_asn : cfg.peer_asn); test->o.use_ibgp ? cfg.local_asn : cfg.peer_asn);
} }
if (test->state != TEST_SUCCESS) if (test->state != TEST_SUCCESS)
return test; return;
/* Fetch default BGP instance. */ /* Fetch default BGP instance. */
test->bgp = bgp_get_default(); test->bgp = bgp_get_default();
@ -638,11 +652,11 @@ static struct test *test_new(const char *desc, bool use_ibgp,
test->state = TEST_INTERNAL_ERROR; test->state = TEST_INTERNAL_ERROR;
test->error = test->error =
str_printf("could not retrieve default bgp instance"); str_printf("could not retrieve default bgp instance");
return test; return;
} }
/* Fetch peer instance. */ /* Fetch peer instance. */
if (use_iface_peer) { if (test->o.use_iface_peer) {
test->peer = test->peer =
peer_lookup_by_conf_if(test->bgp, cfg.peer_interface); peer_lookup_by_conf_if(test->bgp, cfg.peer_interface);
} else { } else {
@ -654,7 +668,7 @@ static struct test *test_new(const char *desc, bool use_ibgp,
test->error = str_printf( test->error = str_printf(
"could not retrieve instance of bgp peer [%s]", "could not retrieve instance of bgp peer [%s]",
cfg.peer_address); cfg.peer_address);
return test; return;
} }
/* Fetch peer-group instance. */ /* Fetch peer-group instance. */
@ -664,8 +678,27 @@ static struct test *test_new(const char *desc, bool use_ibgp,
test->error = str_printf( test->error = str_printf(
"could not retrieve instance of bgp peer-group [%s]", "could not retrieve instance of bgp peer-group [%s]",
cfg.peer_group); cfg.peer_group);
return test; return;
} }
}
static struct test *test_new(const char *desc, bool use_ibgp,
bool use_iface_peer)
{
struct test *test;
test = XCALLOC(MTYPE_TMP, sizeof(struct test));
test->state = TEST_SUCCESS;
test->desc = XSTRDUP(MTYPE_TMP, desc);
test->log = list_new();
test->o.use_ibgp = use_ibgp;
test->o.use_iface_peer = use_iface_peer;
test->vty = vty_new();
test->vty->type = VTY_TERM;
test->vty->node = CONFIG_NODE;
test_initialize(test);
return test; return test;
}; };
@ -822,12 +855,87 @@ static void test_peer_attr(struct test *test, struct test_peer_attr *pa)
return; return;
} }
/* Test Preparation: Switch active address-family. */ /* Test Preparation: Switch and activate address-family. */
if (pa->type == PEER_AT_AF_FLAG || pa->type == PEER_AT_AF_FILTER) { if (pa->type == PEER_AT_AF_FLAG || pa->type == PEER_AT_AF_FILTER) {
test_log(test, "prepare: switch address-family to [%s]", test_log(test, "prepare: switch address-family to [%s]",
afi_safi_print(pa->afi, pa->safi)); afi_safi_print(pa->afi, pa->safi));
test_execute(test, "address-family %s %s", test_execute(test, "address-family %s %s",
str_from_afi(pa->afi), str_from_safi(pa->safi)); str_from_afi(pa->afi), str_from_safi(pa->safi));
test_execute(test, "neighbor %s activate", g->name);
test_execute(test, "neighbor %s activate", p->host);
}
/* Test Case: Set flag on BGP peer. */
test_log(test, "case %02d: set %s [%s] on [%s]", tc++, type, peer_cmd,
p->host);
test_execute(test, "%sneighbor %s %s", ecp, p->host, peer_cmd);
test_config_present(test, "%sneighbor %s %s", ecp, p->host, peer_cmd);
test_config_absent(test, "neighbor %s %s", g->name, pa->cmd);
if (pa->type == PEER_AT_GLOBAL_FLAG || pa->type == PEER_AT_AF_FLAG) {
test_peer_flags(test, p, pa, true, true);
test_peer_flags(test, g->conf, pa, false, false);
} else if (pa->type == PEER_AT_AF_FILTER) {
test_af_filter(test, p, pa, true, true);
test_af_filter(test, g->conf, pa, false, false);
}
/* Test Case: Set flag on BGP peer-group. */
test_log(test, "case %02d: set %s [%s] on [%s]", tc++, type, group_cmd,
g->name);
test_execute(test, "%sneighbor %s %s", ecg, g->name, group_cmd);
test_config_present(test, "%sneighbor %s %s", ecp, p->host, peer_cmd);
test_config_present(test, "%sneighbor %s %s", ecg, g->name, group_cmd);
if (pa->type == PEER_AT_GLOBAL_FLAG || pa->type == PEER_AT_AF_FLAG) {
test_peer_flags(test, p, pa, true, true);
test_peer_flags(test, g->conf, pa, true, false);
} else if (pa->type == PEER_AT_AF_FILTER) {
test_af_filter(test, p, pa, true, true);
test_af_filter(test, g->conf, pa, true, false);
}
/* Test Case: Add BGP peer to peer-group. */
test_log(test, "case %02d: add peer [%s] to group [%s]", tc++, p->host,
g->name);
test_execute(test, "neighbor %s peer-group %s", p->host, g->name);
test_config_present(test, "neighbor %s %speer-group %s", p->host,
p->conf_if ? "interface " : "", g->name);
test_config_present(test, "%sneighbor %s %s", ecp, p->host, peer_cmd);
test_config_present(test, "%sneighbor %s %s", ecg, g->name, group_cmd);
if (pa->type == PEER_AT_GLOBAL_FLAG || pa->type == PEER_AT_AF_FLAG) {
test_peer_flags(test, p, pa, true, true);
test_peer_flags(test, g->conf, pa, true, false);
} else if (pa->type == PEER_AT_AF_FILTER) {
test_af_filter(test, p, pa, true, true);
test_af_filter(test, g->conf, pa, true, false);
}
/* Test Case: Unset flag on BGP peer-group. */
test_log(test, "case %02d: unset %s [%s] on [%s]", tc++, type,
group_cmd, g->name);
test_execute(test, "%sneighbor %s %s", dcg, g->name, group_cmd);
test_config_present(test, "%sneighbor %s %s", ecp, p->host, peer_cmd);
test_config_absent(test, "neighbor %s %s", g->name, pa->cmd);
if (pa->type == PEER_AT_GLOBAL_FLAG || pa->type == PEER_AT_AF_FLAG) {
test_peer_flags(test, p, pa, true, true);
test_peer_flags(test, g->conf, pa, false, false);
} else if (pa->type == PEER_AT_AF_FILTER) {
test_af_filter(test, p, pa, true, true);
test_af_filter(test, g->conf, pa, false, false);
}
/* Test Preparation: Re-initialize test environment. */
test_initialize(test);
p = test->peer;
g = test->group;
/* Test Preparation: Switch and activate address-family. */
if (pa->type == PEER_AT_AF_FLAG || pa->type == PEER_AT_AF_FILTER) {
test_log(test, "prepare: switch address-family to [%s]",
afi_safi_print(pa->afi, pa->safi));
test_execute(test, "address-family %s %s",
str_from_afi(pa->afi), str_from_safi(pa->safi));
test_execute(test, "neighbor %s activate", g->name);
test_execute(test, "neighbor %s activate", p->host);
} }
/* Test Case: Set flag on BGP peer. */ /* Test Case: Set flag on BGP peer. */

View File

@ -80,6 +80,14 @@ TestFlag.okfail('peer\\ipv4-unicast\\default-originate route-map')
TestFlag.okfail('peer\\ipv4-multicast\\default-originate route-map') TestFlag.okfail('peer\\ipv4-multicast\\default-originate route-map')
TestFlag.okfail('peer\\ipv6-unicast\\default-originate route-map') TestFlag.okfail('peer\\ipv6-unicast\\default-originate route-map')
TestFlag.okfail('peer\\ipv6-multicast\\default-originate route-map') TestFlag.okfail('peer\\ipv6-multicast\\default-originate route-map')
TestFlag.okfail('peer\\ipv4-unicast\\distribute-list')
TestFlag.okfail('peer\\ipv4-multicast\\distribute-list')
TestFlag.okfail('peer\\ipv6-unicast\\distribute-list')
TestFlag.okfail('peer\\ipv6-multicast\\distribute-list')
TestFlag.okfail('peer\\ipv4-unicast\\distribute-list')
TestFlag.okfail('peer\\ipv4-multicast\\distribute-list')
TestFlag.okfail('peer\\ipv6-unicast\\distribute-list')
TestFlag.okfail('peer\\ipv6-multicast\\distribute-list')
TestFlag.okfail('peer\\ipv4-unicast\\filter-list') TestFlag.okfail('peer\\ipv4-unicast\\filter-list')
TestFlag.okfail('peer\\ipv4-multicast\\filter-list') TestFlag.okfail('peer\\ipv4-multicast\\filter-list')
TestFlag.okfail('peer\\ipv6-unicast\\filter-list') TestFlag.okfail('peer\\ipv6-unicast\\filter-list')