]> git.puffer.fish Git - matthieu/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>
Tue, 19 Jun 2018 16:17:42 +0000 (18:17 +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>
(cherry picked from commit e7103a9644f32a70a10be8f6372aa9084aa33c2f)

bgpd/bgpd.c
bgpd/bgpd.h
tests/bgpd/test_peer_attr.c
tests/bgpd/test_peer_attr.py

index e0382bf4d2139ed7051a37a48d750e7d481b1ccb..7d70f3fd3dd23ab047864cd0ae2d01361ce92136 100644 (file)
@@ -1800,141 +1800,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);
        }
 }
 
@@ -4702,9 +4672,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,
@@ -4846,7 +4818,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;
@@ -5192,7 +5164,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;
@@ -5526,9 +5498,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];
@@ -5709,9 +5683,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];
@@ -5890,9 +5866,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. */
@@ -6075,9 +6052,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];
@@ -6184,9 +6163,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];
@@ -6297,9 +6278,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 e49ca7619cbf0f688fc698e25ca27e59f172dcb4..06c9b0b72f36fc7d148e63b4e9534fac62e28665 100644 (file)
@@ -1177,13 +1177,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')