]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Fix AF-attribute overrides when binding peer
authorPascal Mathis <mail@pascalmathis.com>
Tue, 12 Jun 2018 15:09:49 +0000 (17:09 +0200)
committerPascal Mathis <mail@pascalmathis.com>
Thu, 14 Jun 2018 16:55:25 +0000 (18:55 +0200)
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>
bgpd/bgpd.c
bgpd/bgpd.h
tests/bgpd/test_peer_attr.c
tests/bgpd/test_peer_attr.py

index 9c84b3042f5d597223e84e3aacd27261bdb702cd..f332c7c9bb53323eb53c2bf0b5606a8245a5cd30 100644 (file)
@@ -1813,141 +1813,111 @@ static void peer_group2peer_config_copy_af(struct peer_group *group,
 {
        int in = FILTER_IN;
        int out = FILTER_OUT;
+       uint32_t pflags_ovrd;
+       uint8_t *pfilter_ovrd;
        struct peer *conf;
-       struct bgp_filter *pfilter;
-       struct bgp_filter *gfilter;
 
        conf = group->conf;
-       pfilter = &peer->filter[afi][safi];
-       gfilter = &conf->filter[afi][safi];
+       pflags_ovrd = peer->af_flags_override[afi][safi];
+       pfilter_ovrd = &peer->filter_override[afi][safi][in];
 
        /* peer af_flags apply */
-       peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
-       peer->af_flags_invert[afi][safi] = conf->af_flags_invert[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];
 
        /* maximum-prefix */
-       peer->pmax[afi][safi] = conf->pmax[afi][safi];
-       peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
-       peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
+       if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_MAX_PREFIX)) {
+               PEER_ATTR_INHERIT(peer, group, pmax[afi][safi]);
+               PEER_ATTR_INHERIT(peer, group, pmax_threshold[afi][safi]);
+               PEER_ATTR_INHERIT(peer, group, pmax_restart[afi][safi]);
+       }
 
        /* 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 */
-       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 */
-       if (conf->default_rmap[afi][safi].name) {
-               if (peer->default_rmap[afi][safi].name)
-                       XFREE(MTYPE_BGP_FILTER_NAME,
-                             peer->default_rmap[afi][safi].name);
-               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;
+       if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_DEFAULT_ORIGINATE)) {
+               PEER_STR_ATTR_INHERIT(peer, group, default_rmap[afi][safi].name,
+                                     MTYPE_ROUTE_MAP_NAME);
+               PEER_ATTR_INHERIT(peer, group, default_rmap[afi][safi].map);
        }
 
        /* inbound filter apply */
-       if (gfilter->dlist[in].name && !pfilter->dlist[in].name) {
-               if (pfilter->dlist[in].name)
-                       XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[in].name);
-               pfilter->dlist[in].name =
-                       XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[in].name);
-               pfilter->dlist[in].alist = gfilter->dlist[in].alist;
+       if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_DISTRIBUTE_LIST)) {
+               PEER_STR_ATTR_INHERIT(peer, group,
+                                     filter[afi][safi].dlist[in].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, group,
+                                 filter[afi][safi].dlist[in].alist);
        }
 
-       if (gfilter->plist[in].name && !pfilter->plist[in].name) {
-               if (pfilter->plist[in].name)
-                       XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[in].name);
-               pfilter->plist[in].name =
-                       XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[in].name);
-               pfilter->plist[in].plist = gfilter->plist[in].plist;
+       if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_PREFIX_LIST)) {
+               PEER_STR_ATTR_INHERIT(peer, group,
+                                     filter[afi][safi].plist[in].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, group,
+                                 filter[afi][safi].plist[in].plist);
        }
 
-       if (gfilter->aslist[in].name && !pfilter->aslist[in].name) {
-               if (pfilter->aslist[in].name)
-                       XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[in].name);
-               pfilter->aslist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME,
-                                                  gfilter->aslist[in].name);
-               pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
+       if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_FILTER_LIST)) {
+               PEER_STR_ATTR_INHERIT(peer, group,
+                                     filter[afi][safi].aslist[in].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, group,
+                                 filter[afi][safi].aslist[in].aslist);
        }
 
-       if (gfilter->map[RMAP_IN].name && !pfilter->map[RMAP_IN].name) {
-               if (pfilter->map[RMAP_IN].name)
-                       XFREE(MTYPE_BGP_FILTER_NAME,
-                             pfilter->map[RMAP_IN].name);
-               pfilter->map[RMAP_IN].name = XSTRDUP(
-                       MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_IN].name);
-               pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
+       if (!CHECK_FLAG(pfilter_ovrd[RMAP_IN], PEER_FT_ROUTE_MAP)) {
+               PEER_STR_ATTR_INHERIT(peer, group,
+                                     filter[afi][safi].map[in].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, group,
+                                 filter[afi][safi].map[RMAP_IN].map);
        }
 
        /* outbound filter apply */
-       if (gfilter->dlist[out].name) {
-               if (pfilter->dlist[out].name)
-                       XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name);
-               pfilter->dlist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME,
-                                                  gfilter->dlist[out].name);
-               pfilter->dlist[out].alist = gfilter->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 (pfilter->plist[out].name)
-                       XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name);
-               pfilter->plist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME,
-                                                  gfilter->plist[out].name);
-               pfilter->plist[out].plist = gfilter->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 (pfilter->aslist[out].name)
-                       XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name);
-               pfilter->aslist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME,
-                                                   gfilter->aslist[out].name);
-               pfilter->aslist[out].aslist = gfilter->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 (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_DISTRIBUTE_LIST)) {
+               PEER_STR_ATTR_INHERIT(peer, group,
+                                     filter[afi][safi].dlist[out].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, group,
+                                 filter[afi][safi].dlist[out].alist);
        }
 
-       if (gfilter->map[RMAP_OUT].name) {
-               if (pfilter->map[RMAP_OUT].name)
-                       XFREE(MTYPE_BGP_FILTER_NAME,
-                             pfilter->map[RMAP_OUT].name);
-               pfilter->map[RMAP_OUT].name = XSTRDUP(
-                       MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_OUT].name);
-               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 (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_PREFIX_LIST)) {
+               PEER_STR_ATTR_INHERIT(peer, group,
+                                     filter[afi][safi].plist[out].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, group,
+                                 filter[afi][safi].plist[out].plist);
        }
 
-       if (gfilter->usmap.name) {
-               if (pfilter->usmap.name)
-                       XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name);
-               pfilter->usmap.name =
-                       XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->usmap.name);
-               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;
+       if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_FILTER_LIST)) {
+               PEER_STR_ATTR_INHERIT(peer, group,
+                                     filter[afi][safi].aslist[out].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, group,
+                                 filter[afi][safi].aslist[out].aslist);
+       }
+
+       if (!CHECK_FLAG(pfilter_ovrd[RMAP_OUT], PEER_FT_ROUTE_MAP)) {
+               PEER_STR_ATTR_INHERIT(peer, group,
+                                     filter[afi][safi].map[RMAP_OUT].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, group,
+                                 filter[afi][safi].map[RMAP_OUT].map);
+       }
+
+       /* nondirectional filter apply */
+       if (!CHECK_FLAG(pfilter_ovrd[0], PEER_FT_UNSUPPRESS_MAP)) {
+               PEER_STR_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.map);
        }
 }
 
@@ -4766,9 +4736,11 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
        if (peer_group_active(peer)) {
                peer_af_flag_inherit(peer, afi, safi,
                                     PEER_FLAG_DEFAULT_ORIGINATE);
-               PEER_STR_ATTR_INHERIT(MTYPE_ROUTE_MAP_NAME, peer,
-                                     default_rmap[afi][safi].name);
-               PEER_ATTR_INHERIT(peer, default_rmap[afi][safi].map);
+               PEER_STR_ATTR_INHERIT(peer, peer->group,
+                                     default_rmap[afi][safi].name,
+                                     MTYPE_ROUTE_MAP_NAME);
+               PEER_ATTR_INHERIT(peer, peer->group,
+                                 default_rmap[afi][safi].map);
        } else {
                /* Otherwise remove flag and configuration from peer. */
                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. */
        if (peer_group_active(peer)) {
                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);
                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_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);
 
                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. */
        if (peer_group_active(peer)) {
-               PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
-                                     filter[afi][safi].dlist[direct].name);
-               PEER_ATTR_INHERIT(peer, filter[afi][safi].dlist[direct].alist);
+               PEER_STR_ATTR_INHERIT(peer, peer->group,
+                                     filter[afi][safi].dlist[direct].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, peer->group,
+                                 filter[afi][safi].dlist[direct].alist);
        } else {
                /* Otherwise remove configuration from peer. */
                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. */
        if (peer_group_active(peer)) {
-               PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
-                                     filter[afi][safi].plist[direct].name);
-               PEER_ATTR_INHERIT(peer, filter[afi][safi].plist[direct].plist);
+               PEER_STR_ATTR_INHERIT(peer, peer->group,
+                                     filter[afi][safi].plist[direct].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, peer->group,
+                                 filter[afi][safi].plist[direct].plist);
        } else {
                /* Otherwise remove configuration from peer. */
                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. */
        if (peer_group_active(peer)) {
-               PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
-                                     filter[afi][safi].aslist[direct].name);
-               PEER_ATTR_INHERIT(peer,
+               PEER_STR_ATTR_INHERIT(peer, peer->group,
+                                     filter[afi][safi].aslist[direct].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, peer->group,
                                  filter[afi][safi].aslist[direct].aslist);
        } else {
                /* 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. */
        if (peer_group_active(peer)) {
-               PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
-                                     filter[afi][safi].map[direct].name);
-               PEER_ATTR_INHERIT(peer, filter[afi][safi].map[direct].map);
+               PEER_STR_ATTR_INHERIT(peer, peer->group,
+                                     filter[afi][safi].map[direct].name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, peer->group,
+                                 filter[afi][safi].map[direct].map);
        } else {
                /* Otherwise remove configuration from peer. */
                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. */
        if (peer_group_active(peer)) {
-               PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
-                                     filter[afi][safi].usmap.name);
-               PEER_ATTR_INHERIT(peer, filter[afi][safi].usmap.map);
+               PEER_STR_ATTR_INHERIT(peer, peer->group,
+                                     filter[afi][safi].usmap.name,
+                                     MTYPE_BGP_FILTER_NAME);
+               PEER_ATTR_INHERIT(peer, peer->group,
+                                 filter[afi][safi].usmap.map);
        } else {
                /* Otherwise remove configuration from peer. */
                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_WARNING);
-               PEER_ATTR_INHERIT(peer, pmax[afi][safi]);
-               PEER_ATTR_INHERIT(peer, pmax_threshold[afi][safi]);
-               PEER_ATTR_INHERIT(peer, pmax_restart[afi][safi]);
+               PEER_ATTR_INHERIT(peer, peer->group, pmax[afi][safi]);
+               PEER_ATTR_INHERIT(peer, peer->group, pmax_threshold[afi][safi]);
+               PEER_ATTR_INHERIT(peer, peer->group, pmax_restart[afi][safi]);
 
                return 0;
        }
index 4048e8a8d91d97aa261d1ee6b68fb7887ea4ad89..fdc363d1f48a2d6cd7b3680d09e7fd6fe9d50249 100644 (file)
@@ -1184,13 +1184,14 @@ struct peer {
 DECLARE_QOBJ_TYPE(peer)
 
 /* Inherit peer attribute from peer-group. */
-#define PEER_ATTR_INHERIT(peer, attr) ((peer)->attr = (peer)->group->conf->attr)
-#define PEER_STR_ATTR_INHERIT(mt, peer, attr)                                  \
+#define PEER_ATTR_INHERIT(peer, group, attr)                                   \
+       ((peer)->attr = (group)->conf->attr)
+#define PEER_STR_ATTR_INHERIT(peer, group, attr, mt)                           \
        do {                                                                   \
                if ((peer)->attr)                                              \
                        XFREE(mt, (peer)->attr);                               \
-               if ((peer)->group->conf->attr)                                 \
-                       (peer)->attr = XSTRDUP(mt, (peer)->group->conf->attr); \
+               if ((group)->conf->attr)                                       \
+                       (peer)->attr = XSTRDUP(mt, (group)->conf->attr);       \
                else                                                           \
                        (peer)->attr = NULL;                                   \
        } while (0)
index e4a3c6bb8aad6463ebb44e39af6622459f21765f..3862028bb7553990643568c5e0bc3386e4fcf46d 100644 (file)
@@ -56,6 +56,11 @@ struct test {
        struct bgp *bgp;
        struct peer *peer;
        struct peer_group *group;
+
+       struct {
+               bool use_ibgp;
+               bool use_iface_peer;
+       } o;
 };
 
 struct test_config {
@@ -256,6 +261,22 @@ static struct test_peer_attr test_peer_attrs[] = {
                .group_cmd = "default-originate route-map RM-GROUP",
                .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",
                .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);
 }
 
-static struct test *test_new(const char *desc, bool use_ibgp,
-                            bool use_iface_peer)
+static void test_initialize(struct test *test)
 {
-       struct test *test;
        union sockunion su;
 
-       test = XCALLOC(MTYPE_TMP, sizeof(struct test));
-       test->state = TEST_SUCCESS;
-       test->desc = XSTRDUP(MTYPE_TMP, desc);
-       test->log = list_new();
-
-       test->vty = vty_new();
-       test->vty->type = VTY_TERM;
-       test->vty->node = CONFIG_NODE;
+       /* Log message about (re)-initialization */
+       test_log(test, "prepare: %sinitialize bgp test environment",
+                test->bgp ? "re-" : "");
 
        /* Attempt gracefully to purge previous BGP configuration. */
        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, "no bgp default ipv4-unicast");
        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 remote-as %d",
                             cfg.peer_interface,
-                            use_ibgp ? cfg.local_asn : cfg.peer_asn);
+                            test->o.use_ibgp ? cfg.local_asn : cfg.peer_asn);
        } else {
                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)
-               return test;
+               return;
 
        /* Fetch default BGP instance. */
        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->error =
                        str_printf("could not retrieve default bgp instance");
-               return test;
+               return;
        }
 
        /* Fetch peer instance. */
-       if (use_iface_peer) {
+       if (test->o.use_iface_peer) {
                test->peer =
                        peer_lookup_by_conf_if(test->bgp, cfg.peer_interface);
        } else {
@@ -654,7 +668,7 @@ static struct test *test_new(const char *desc, bool use_ibgp,
                test->error = str_printf(
                        "could not retrieve instance of bgp peer [%s]",
                        cfg.peer_address);
-               return test;
+               return;
        }
 
        /* Fetch peer-group instance. */
@@ -664,8 +678,27 @@ static struct test *test_new(const char *desc, bool use_ibgp,
                test->error = str_printf(
                        "could not retrieve instance of bgp peer-group [%s]",
                        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;
 };
@@ -822,12 +855,87 @@ static void test_peer_attr(struct test *test, struct test_peer_attr *pa)
                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) {
+               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_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. */
index 2c1623dea2939152012a84bd22b77add7cdaafe1..bd377ca3ad4308c38a4e45f6b8968c2d839627f1 100644 (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\\ipv6-unicast\\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-multicast\\filter-list')
 TestFlag.okfail('peer\\ipv6-unicast\\filter-list')