Merge pull request #7189 from maduri111/bgpd-conditional-adv

bgpd: conditional advertisement
This commit is contained in:
Rafael Zalamena 2020-10-27 12:24:24 -03:00 committed by GitHub
commit 7f2f38c62f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 2104 additions and 6 deletions

343
bgpd/bgp_conditional_adv.c Normal file
View File

@ -0,0 +1,343 @@
/*
* BGP Conditional advertisement
* Copyright (C) 2020 Samsung R&D Institute India - Bangalore.
* Madhurilatha Kuruganti
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "bgpd/bgp_conditional_adv.h"
const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
static route_map_result_t
bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table *table,
struct route_map *rmap)
{
struct attr dummy_attr = {0};
struct bgp_dest *dest;
struct bgp_path_info *pi;
struct bgp_path_info path = {0};
struct bgp_path_info_extra path_extra = {0};
const struct prefix *dest_p;
route_map_result_t ret = RMAP_DENYMATCH;
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
dest_p = bgp_dest_get_prefix(dest);
assert(dest_p);
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
dummy_attr = *pi->attr;
/* Fill temp path_info */
prep_for_rmap_apply(&path, &path_extra, dest, pi,
pi->peer, &dummy_attr);
RESET_FLAG(dummy_attr.rmap_change_flags);
ret = route_map_apply(rmap, dest_p, RMAP_BGP, &path);
if (ret != RMAP_PERMITMATCH)
bgp_attr_flush(&dummy_attr);
else {
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug(
"%s: Condition map routes present in BGP table",
__func__);
return ret;
}
}
}
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("%s: Condition map routes not present in BGP table",
__func__);
return ret;
}
static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
safi_t safi, struct bgp_table *table,
struct route_map *rmap,
enum update_type update_type)
{
int addpath_capable;
struct bgp_dest *dest;
struct bgp_path_info *pi;
struct bgp_path_info path;
struct peer_af *paf;
const struct prefix *dest_p;
struct update_subgroup *subgrp;
struct attr dummy_attr = {0}, attr = {0};
struct bgp_path_info_extra path_extra = {0};
paf = peer_af_find(peer, afi, safi);
if (!paf)
return;
subgrp = PAF_SUBGRP(paf);
/* Ignore if subgroup doesn't exist (implies AF is not negotiated) */
if (!subgrp)
return;
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("%s: %s routes to/from %s for %s", __func__,
update_type == ADVERTISE ? "Advertise" : "Withdraw",
peer->host, get_afi_safi_str(afi, safi, false));
addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
dest_p = bgp_dest_get_prefix(dest);
assert(dest_p);
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
dummy_attr = *pi->attr;
/* Fill temp path_info */
prep_for_rmap_apply(&path, &path_extra, dest, pi,
pi->peer, &dummy_attr);
RESET_FLAG(dummy_attr.rmap_change_flags);
if (route_map_apply(rmap, dest_p, RMAP_BGP, &path)
!= RMAP_PERMITMATCH) {
bgp_attr_flush(&dummy_attr);
continue;
}
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
|| (addpath_capable
&& bgp_addpath_tx_path(
peer->addpath_type[afi][safi],
pi))) {
/* Skip route-map checks in
* subgroup_announce_check while executing from
* the conditional advertise scanner process.
* otherwise when route-map is also configured
* on same peer, routes in advertise-map may not
* be advertised as expected.
*/
if ((update_type == ADVERTISE)
&& subgroup_announce_check(dest, pi, subgrp,
dest_p, &attr,
true))
bgp_adj_out_set_subgroup(dest, subgrp,
&attr, pi);
else {
/* If default originate is enabled for
* the peer, do not send explicit
* withdraw. This will prevent deletion
* of default route advertised through
* default originate.
*/
if (CHECK_FLAG(
peer->af_flags[afi][safi],
PEER_FLAG_DEFAULT_ORIGINATE)
&& is_default_prefix(dest_p))
break;
bgp_adj_out_unset_subgroup(
dest, subgrp, 1,
bgp_addpath_id_for_peer(
peer, afi, safi,
&pi->tx_addpath));
}
}
}
}
}
/* Handler of conditional advertisement timer event.
* Each route in the condition-map is evaluated.
*/
static int bgp_conditional_adv_timer(struct thread *t)
{
afi_t afi;
safi_t safi;
int pfx_rcd_safi;
struct bgp *bgp = NULL;
struct peer *peer = NULL;
struct peer_af *paf = NULL;
struct bgp_table *table = NULL;
struct bgp_filter *filter = NULL;
struct listnode *node, *nnode = NULL;
struct update_subgroup *subgrp = NULL;
route_map_result_t ret;
bgp = THREAD_ARG(t);
assert(bgp);
thread_add_timer(bm->master, bgp_conditional_adv_timer, bgp,
CONDITIONAL_ROUTES_POLL_TIME, &bgp->t_condition_check);
/* loop through each peer and advertise or withdraw routes if
* advertise-map is configured and prefix(es) in condition-map
* does exist(exist-map)/not exist(non-exist-map) in BGP table
* based on condition(exist-map or non-exist map)
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
continue;
if (peer->status != Established)
continue;
FOREACH_AFI_SAFI (afi, safi) {
if (strmatch(get_afi_safi_str(afi, safi, true),
"Unknown"))
continue;
if (!peer->afc_nego[afi][safi])
continue;
/* labeled-unicast routes are installed in the unicast
* table so in order to display the correct PfxRcd value
* we must look at SAFI_UNICAST
*/
pfx_rcd_safi = (safi == SAFI_LABELED_UNICAST)
? SAFI_UNICAST
: safi;
table = bgp->rib[afi][pfx_rcd_safi];
if (!table)
continue;
filter = &peer->filter[afi][safi];
if (!filter->advmap.aname || !filter->advmap.cname
|| !filter->advmap.amap || !filter->advmap.cmap)
continue;
if (!peer->advmap_config_change[afi][safi]
&& !peer->advmap_table_change)
continue;
if (BGP_DEBUG(update, UPDATE_OUT)) {
if (peer->advmap_table_change)
zlog_debug(
"%s: %s - routes changed in BGP table.",
__func__, peer->host);
if (peer->advmap_config_change[afi][safi])
zlog_debug(
"%s: %s for %s - advertise/condition map configuration is changed.",
__func__, peer->host,
get_afi_safi_str(afi, safi,
false));
}
/* cmap (route-map attached to exist-map or
* non-exist-map) map validation
*/
ret = bgp_check_rmap_prefixes_in_bgp_table(
table, filter->advmap.cmap);
/* Derive conditional advertisement status from
* condition and return value of condition-map
* validation.
*/
if (filter->advmap.condition == CONDITION_EXIST)
filter->advmap.update_type =
(ret == RMAP_PERMITMATCH) ? ADVERTISE
: WITHDRAW;
else
filter->advmap.update_type =
(ret == RMAP_PERMITMATCH) ? WITHDRAW
: ADVERTISE;
/* Send regular update as per the existing policy.
* There is a change in route-map, match-rule, ACLs,
* or route-map filter configuration on the same peer.
*/
if (peer->advmap_config_change[afi][safi]) {
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug(
"%s: Configuration is changed on peer %s for %s, send the normal update first.",
__func__, peer->host,
get_afi_safi_str(afi, safi,
false));
paf = peer_af_find(peer, afi, safi);
if (paf) {
update_subgroup_split_peer(paf, NULL);
subgrp = paf->subgroup;
if (subgrp && subgrp->update_group)
subgroup_announce_table(
paf->subgroup, NULL);
}
peer->advmap_config_change[afi][safi] = false;
}
/* Send update as per the conditional advertisement */
bgp_conditional_adv_routes(peer, afi, safi, table,
filter->advmap.amap,
filter->advmap.update_type);
}
peer->advmap_table_change = false;
}
return 0;
}
void bgp_conditional_adv_enable(struct peer *peer, afi_t afi, safi_t safi)
{
struct bgp *bgp = peer->bgp;
assert(bgp);
/* This flag is used to monitor conditional routes status in BGP table,
* and advertise/withdraw routes only when there is a change in BGP
* table w.r.t conditional routes
*/
peer->advmap_config_change[afi][safi] = true;
/* advertise-map is already configured on atleast one of its
* neighbors (AFI/SAFI). So just increment the counter.
*/
if (++bgp->condition_filter_count > 1) {
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("%s: condition_filter_count %d", __func__,
bgp->condition_filter_count);
return;
}
/* Register for conditional routes polling timer */
thread_add_timer(bm->master, bgp_conditional_adv_timer, bgp,
CONDITIONAL_ROUTES_POLL_TIME, &bgp->t_condition_check);
}
void bgp_conditional_adv_disable(struct peer *peer, afi_t afi, safi_t safi)
{
struct bgp *bgp = peer->bgp;
assert(bgp);
/* advertise-map is not configured on any of its neighbors or
* it is configured on more than one neighbor(AFI/SAFI).
* So there's nothing to do except decrementing the counter.
*/
if (--bgp->condition_filter_count != 0) {
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("%s: condition_filter_count %d", __func__,
bgp->condition_filter_count);
return;
}
/* Last filter removed. So cancel conditional routes polling thread. */
THREAD_OFF(bgp->t_condition_check);
}

View File

@ -0,0 +1,47 @@
/*
* BGP Conditional advertisement
* Copyright (C) 2020 Samsung R&D Institute India - Bangalore.
* Madhurilatha Kuruganti
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _FRR_BGP_CONDITION_ADV_H
#define _FRR_BGP_CONDITION_ADV_H
#include <zebra.h>
#include "prefix.h"
#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_updgrp.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Polling time for monitoring condition-map routes in route table */
#define CONDITIONAL_ROUTES_POLL_TIME 60
extern void bgp_conditional_adv_enable(struct peer *peer, afi_t afi,
safi_t safi);
extern void bgp_conditional_adv_disable(struct peer *peer, afi_t afi,
safi_t safi);
#ifdef __cplusplus
}
#endif
#endif /* _FRR_BGP_CONDITION_ADV_H */

View File

@ -1783,6 +1783,9 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
peer->update_time = bgp_clock();
/* Notify BGP Conditional advertisement scanner process */
peer->advmap_table_change = true;
return Receive_UPDATE_message;
}

View File

@ -1660,6 +1660,33 @@ void bgp_attr_add_gshut_community(struct attr *attr)
}
/* Notify BGP Conditional advertisement scanner process. */
void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
{
struct peer *temp_peer;
struct peer *peer = SUBGRP_PEER(subgrp);
struct listnode *temp_node, *temp_nnode = NULL;
afi_t afi = SUBGRP_AFI(subgrp);
safi_t safi = SUBGRP_SAFI(subgrp);
struct bgp *bgp = SUBGRP_INST(subgrp);
struct bgp_filter *filter = &peer->filter[afi][safi];
if (!ADVERTISE_MAP_NAME(filter))
return;
for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
continue;
if (peer != temp_peer)
continue;
temp_peer->advmap_table_change = true;
break;
}
}
static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
{
if (family == AF_INET) {
@ -1674,7 +1701,8 @@ static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
struct update_subgroup *subgrp,
const struct prefix *p, struct attr *attr)
const struct prefix *p, struct attr *attr,
bool skip_rmap_check)
{
struct bgp_filter *filter;
struct peer *from;
@ -1989,7 +2017,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
bgp_peer_as_override(bgp, afi, safi, peer, attr);
/* Route map & unsuppress-map apply. */
if (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi)) {
if (!skip_rmap_check
&& (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
struct bgp_path_info rmap_path = {0};
struct bgp_path_info_extra dummy_rmap_path_extra = {0};
struct attr dummy_attr = {0};
@ -2487,7 +2516,8 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
/* Announcement to the subgroup. If the route is filtered withdraw it.
*/
if (selected) {
if (subgroup_announce_check(dest, selected, subgrp, p, &attr))
if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
false))
bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
else
bgp_adj_out_unset_subgroup(dest, subgrp, 1,
@ -4360,6 +4390,10 @@ static int bgp_announce_route_timer_expired(struct thread *t)
return 0;
peer_af_announce_route(paf, 1);
/* Notify BGP conditional advertisement scanner percess */
peer->advmap_config_change[paf->afi][paf->safi] = true;
return 0;
}

View File

@ -454,6 +454,14 @@ struct bgp_aggregate {
#define UNSUPPRESS_MAP_NAME(F) ((F)->usmap.name)
#define UNSUPPRESS_MAP(F) ((F)->usmap.map)
#define ADVERTISE_MAP_NAME(F) ((F)->advmap.aname)
#define ADVERTISE_MAP(F) ((F)->advmap.amap)
#define ADVERTISE_CONDITION(F) ((F)->advmap.condition)
#define CONDITION_MAP_NAME(F) ((F)->advmap.cname)
#define CONDITION_MAP(F) ((F)->advmap.cmap)
/* path PREFIX (addpath rxid NUMBER) */
#define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32
@ -663,6 +671,8 @@ extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
json_object *json);
extern void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp);
extern void subgroup_process_announce_selected(struct update_subgroup *subgrp,
struct bgp_path_info *selected,
struct bgp_dest *dest,
@ -671,7 +681,8 @@ extern void subgroup_process_announce_selected(struct update_subgroup *subgrp,
extern bool subgroup_announce_check(struct bgp_dest *dest,
struct bgp_path_info *pi,
struct update_subgroup *subgrp,
const struct prefix *p, struct attr *attr);
const struct prefix *p, struct attr *attr,
bool skip_rmap_check);
extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer);
extern void bgp_process_queues_drain_immediate(void);

View File

@ -3695,9 +3695,22 @@ static void bgp_route_map_process_peer(const char *rmap_name,
if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
filter->usmap.map = map;
if (filter->advmap.aname
&& (strcmp(rmap_name, filter->advmap.aname) == 0)) {
filter->advmap.amap = map;
}
if (filter->advmap.cname
&& (strcmp(rmap_name, filter->advmap.cname) == 0)) {
filter->advmap.cmap = map;
}
if (peer->default_rmap[afi][safi].name
&& (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
peer->default_rmap[afi][safi].map = map;
/* Notify BGP conditional advertisement scanner percess */
peer->advmap_config_change[afi][safi] = true;
}
static void bgp_route_map_update_peer_group(const char *rmap_name,

View File

@ -195,6 +195,19 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
MTYPE_BGP_FILTER_NAME, UNSUPPRESS_MAP_NAME(srcfilter));
UNSUPPRESS_MAP(dstfilter) = UNSUPPRESS_MAP(srcfilter);
}
if (ADVERTISE_MAP_NAME(srcfilter)) {
ADVERTISE_MAP_NAME(dstfilter) = XSTRDUP(
MTYPE_BGP_FILTER_NAME, ADVERTISE_MAP_NAME(srcfilter));
ADVERTISE_MAP(dstfilter) = ADVERTISE_MAP(srcfilter);
ADVERTISE_CONDITION(dstfilter) = ADVERTISE_CONDITION(srcfilter);
}
if (CONDITION_MAP_NAME(srcfilter)) {
CONDITION_MAP_NAME(dstfilter) = XSTRDUP(
MTYPE_BGP_FILTER_NAME, CONDITION_MAP_NAME(srcfilter));
CONDITION_MAP(dstfilter) = CONDITION_MAP(srcfilter);
}
}
/**
@ -218,6 +231,10 @@ static void conf_release(struct peer *src, afi_t afi, safi_t safi)
XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name);
XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->advmap.aname);
XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->advmap.cname);
XFREE(MTYPE_BGP_PEER_HOST, src->host);
}
@ -353,6 +370,11 @@ static unsigned int updgrp_hash_key_make(const void *p)
strlen(filter->usmap.name), SEED1),
key);
if (filter->advmap.aname)
key = jhash_1word(jhash(filter->advmap.aname,
strlen(filter->advmap.aname), SEED1),
key);
if (peer->default_rmap[afi][safi].name)
key = jhash_1word(
jhash(peer->default_rmap[afi][safi].name,
@ -481,6 +503,12 @@ static bool updgrp_hash_cmp(const void *p1, const void *p2)
&& strcmp(fl1->usmap.name, fl2->usmap.name)))
return false;
if ((fl1->advmap.aname && !fl2->advmap.aname)
|| (!fl1->advmap.aname && fl2->advmap.aname)
|| (fl1->advmap.aname && fl2->advmap.aname
&& strcmp(fl1->advmap.aname, fl2->advmap.aname)))
return false;
if ((pe1->default_rmap[afi][safi].name
&& !pe2->default_rmap[afi][safi].name)
|| (!pe1->default_rmap[afi][safi].name

View File

@ -215,6 +215,9 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
}
}
}
/* Notify BGP Conditional advertisement */
bgp_notify_conditional_adv_scanner(subgrp);
}
return UPDWALK_CONTINUE;
@ -642,7 +645,8 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
peer->addpath_type[afi][safi],
ri))) {
if (subgroup_announce_check(dest, ri, subgrp,
dest_p, &attr))
dest_p, &attr,
false))
bgp_adj_out_set_subgroup(dest, subgrp,
&attr, ri);
else {
@ -827,7 +831,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
if (subgroup_announce_check(
dest, pi, subgrp,
bgp_dest_get_prefix(dest),
&attr))
&attr, false))
bgp_adj_out_set_subgroup(
dest, subgrp, &attr,
pi);

View File

@ -7175,6 +7175,68 @@ ALIAS_HIDDEN(no_neighbor_filter_list, no_neighbor_filter_list_hidden_cmd,
"Filter incoming routes\n"
"Filter outgoing routes\n")
/* Set advertise-map to the peer. */
static int peer_advertise_map_set_vty(struct vty *vty, const char *ip_str,
afi_t afi, safi_t safi,
const char *advertise_str,
const char *condition_str, bool condition,
bool set)
{
int ret = CMD_WARNING_CONFIG_FAILED;
struct peer *peer;
struct route_map *advertise_map;
struct route_map *condition_map;
peer = peer_and_group_lookup_vty(vty, ip_str);
if (!peer)
return ret;
condition_map = route_map_lookup_warn_noexist(vty, condition_str);
advertise_map = route_map_lookup_warn_noexist(vty, advertise_str);
if (set)
ret = peer_advertise_map_set(peer, afi, safi, advertise_str,
advertise_map, condition_str,
condition_map, condition);
else
ret = peer_advertise_map_unset(peer, afi, safi, advertise_str,
advertise_map, condition_str,
condition_map, condition);
return bgp_vty_return(vty, ret);
}
DEFPY (neighbor_advertise_map,
neighbor_advertise_map_cmd,
"[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map WORD$advertise_str <exist-map|non-exist-map>$exist WORD$condition_str",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Route-map to conditionally advertise routes\n"
"Name of advertise map\n"
"Advertise routes only if prefixes in exist-map are installed in BGP table\n"
"Advertise routes only if prefixes in non-exist-map are not installed in BGP table\n"
"Name of the exist or non exist map\n")
{
bool condition = CONDITION_EXIST;
if (!strcmp(exist, "non-exist-map"))
condition = CONDITION_NON_EXIST;
return peer_advertise_map_set_vty(vty, neighbor, bgp_node_afi(vty),
bgp_node_safi(vty), advertise_str,
condition_str, condition, !no);
}
ALIAS_HIDDEN(neighbor_advertise_map, neighbor_advertise_map_hidden_cmd,
"[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map WORD$advertise_str <exist-map|non-exist-map>$exist WORD$condition_str",
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
"Route-map to conditionally advertise routes\n"
"Name of advertise map\n"
"Advertise routes only if prefixes in exist-map are installed in BGP table\n"
"Advertise routes only if prefixes in non-exist-map are not installed in BGP table\n"
"Name of the exist or non exist map\n")
/* Set route-map to the peer. */
static int peer_route_map_set_vty(struct vty *vty, const char *ip_str,
afi_t afi, safi_t safi, const char *name_str,
@ -10879,6 +10941,7 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
json_object *json_prefA = NULL;
json_object *json_prefB = NULL;
json_object *json_addr = NULL;
json_object *json_advmap = NULL;
if (use_json) {
json_addr = json_object_new_object();
@ -11153,6 +11216,26 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
"selectiveUnsuppressRouteMap",
filter->usmap.name);
/* advertise-map */
if (filter->advmap.aname) {
json_advmap = json_object_new_object();
json_object_string_add(json_advmap, "condition",
filter->advmap.condition
? "EXIST"
: "NON_EXIST");
json_object_string_add(json_advmap, "conditionMap",
filter->advmap.cname);
json_object_string_add(json_advmap, "advertiseMap",
filter->advmap.aname);
json_object_string_add(json_advmap, "advertiseStatus",
filter->advmap.update_type
== ADVERTISE
? "Advertise"
: "Withdraw");
json_object_object_add(json_addr, "advertiseMap",
json_advmap);
}
/* Receive prefix count */
json_object_int_add(json_addr, "acceptedPrefixCounter",
p->pcount[afi][safi]);
@ -11448,6 +11531,20 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
filter->usmap.map ? "*" : "",
filter->usmap.name);
/* advertise-map */
if (filter->advmap.aname && filter->advmap.cname)
vty_out(vty,
" Condition %s, Condition-map %s%s, Advertise-map %s%s, status: %s\n",
filter->advmap.condition ? "EXIST"
: "NON_EXIST",
filter->advmap.cmap ? "*" : "",
filter->advmap.cname,
filter->advmap.amap ? "*" : "",
filter->advmap.aname,
filter->advmap.update_type == ADVERTISE
? "Advertise"
: "Withdraw");
/* Receive prefix count */
vty_out(vty, " %u accepted prefixes\n",
p->pcount[afi][safi]);
@ -15112,6 +15209,10 @@ static bool peergroup_filter_check(struct peer *peer, afi_t afi, safi_t safi,
return !!(filter->map[direct].name);
case PEER_FT_UNSUPPRESS_MAP:
return !!(filter->usmap.name);
case PEER_FT_ADVERTISE_MAP:
return !!(filter->advmap.aname
&& ((filter->advmap.condition == direct)
&& filter->advmap.cname));
default:
return false;
}
@ -15297,6 +15398,18 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
filter->usmap.name);
/* advertise-map : always applied in OUT direction*/
if (peergroup_filter_check(peer, afi, safi, PEER_FT_ADVERTISE_MAP,
CONDITION_NON_EXIST))
vty_out(vty,
" neighbor %s advertise-map %s non-exist-map %s\n",
addr, filter->advmap.aname, filter->advmap.cname);
if (peergroup_filter_check(peer, afi, safi, PEER_FT_ADVERTISE_MAP,
CONDITION_EXIST))
vty_out(vty, " neighbor %s advertise-map %s exist-map %s\n",
addr, filter->advmap.aname, filter->advmap.cname);
/* filter-list. */
if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
FILTER_IN))
@ -17501,6 +17614,17 @@ void bgp_vty_init(void)
install_element(BGP_VPNV6_NODE, &neighbor_unsuppress_map_cmd);
install_element(BGP_VPNV6_NODE, &no_neighbor_unsuppress_map_cmd);
/* "neighbor advertise-map" commands. */
install_element(BGP_NODE, &neighbor_advertise_map_hidden_cmd);
install_element(BGP_IPV4_NODE, &neighbor_advertise_map_cmd);
install_element(BGP_IPV4M_NODE, &neighbor_advertise_map_cmd);
install_element(BGP_IPV4L_NODE, &neighbor_advertise_map_cmd);
install_element(BGP_IPV6_NODE, &neighbor_advertise_map_cmd);
install_element(BGP_IPV6M_NODE, &neighbor_advertise_map_cmd);
install_element(BGP_IPV6L_NODE, &neighbor_advertise_map_cmd);
install_element(BGP_VPNV4_NODE, &neighbor_advertise_map_cmd);
install_element(BGP_VPNV6_NODE, &neighbor_advertise_map_cmd);
/* neighbor maximum-prefix-out commands. */
install_element(BGP_NODE, &neighbor_maximum_prefix_out_cmd);
install_element(BGP_NODE, &no_neighbor_maximum_prefix_out_cmd);

View File

@ -54,6 +54,7 @@
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_errors.h"
#include "bgpd/bgp_community.h"
#include "bgpd/bgp_conditional_adv.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_regex.h"
#include "bgpd/bgp_clist.h"
@ -6585,6 +6586,172 @@ int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
return 0;
}
static void peer_advertise_map_filter_update(struct peer *peer, afi_t afi,
safi_t safi, const char *amap_name,
struct route_map *amap,
const char *cmap_name,
struct route_map *cmap,
bool condition, bool set)
{
struct bgp_filter *filter;
bool filter_exists = false;
filter = &peer->filter[afi][safi];
/* advertise-map is already configured. */
if (filter->advmap.aname) {
filter_exists = true;
XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.aname);
XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.cname);
}
route_map_counter_decrement(filter->advmap.amap);
/* Removed advertise-map configuration */
if (!set) {
memset(filter, 0, sizeof(struct bgp_filter));
/* decrement condition_filter_count delete timer if
* this is the last advertise-map to be removed.
*/
if (filter_exists)
bgp_conditional_adv_disable(peer, afi, safi);
return;
}
/* Update filter data with newly configured values. */
filter->advmap.aname = XSTRDUP(MTYPE_BGP_FILTER_NAME, amap_name);
filter->advmap.cname = XSTRDUP(MTYPE_BGP_FILTER_NAME, cmap_name);
filter->advmap.amap = amap;
filter->advmap.cmap = cmap;
filter->advmap.condition = condition;
route_map_counter_increment(filter->advmap.amap);
peer->advmap_config_change[afi][safi] = true;
/* Increment condition_filter_count and/or create timer. */
if (!filter_exists) {
filter->advmap.update_type = ADVERTISE;
bgp_conditional_adv_enable(peer, afi, safi);
}
}
/* Set advertise-map to the peer but do not process peer route updates here. *
* Hold filter changes until the conditional routes polling thread is called *
* AS we need to advertise/withdraw prefixes (in advertise-map) based on the *
* condition (exist-map/non-exist-map) and routes(specified in condition-map) *
* in BGP table. So do not call peer_on_policy_change() here, only create *
* polling timer thread, update filters and increment condition_filter_count.
*/
int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
const char *advertise_name,
struct route_map *advertise_map,
const char *condition_name,
struct route_map *condition_map, bool condition)
{
struct peer *member;
struct listnode *node, *nnode;
/* Set configuration on peer. */
peer_advertise_map_filter_update(peer, afi, safi, advertise_name,
advertise_map, condition_name,
condition_map, condition, true);
/* Check if handling a regular peer & Skip peer-group mechanics. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Set override-flag and process peer route updates. */
SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
PEER_FT_ADVERTISE_MAP);
return 0;
}
/*
* Set configuration on all peer-group members, unless they are
* explicitely overriding peer-group configuration.
*/
for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
/* Skip peers with overridden configuration. */
if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
PEER_FT_ADVERTISE_MAP))
continue;
/* Set configuration on peer-group member. */
peer_advertise_map_filter_update(
member, afi, safi, advertise_name, advertise_map,
condition_name, condition_map, condition, true);
}
return 0;
}
/* Unset advertise-map from the peer. */
int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
const char *advertise_name,
struct route_map *advertise_map,
const char *condition_name,
struct route_map *condition_map, bool condition)
{
struct peer *member;
struct listnode *node, *nnode;
/* advertise-map is not configured */
if (!peer->filter[afi][safi].advmap.aname)
return 0;
/* Unset override-flag unconditionally. */
UNSET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
PEER_FT_ADVERTISE_MAP);
/* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
PEER_STR_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].advmap.aname,
MTYPE_BGP_FILTER_NAME);
PEER_ATTR_INHERIT(peer, peer->group,
filter[afi][safi].advmap.amap);
} else
peer_advertise_map_filter_update(
peer, afi, safi, advertise_name, advertise_map,
condition_name, condition_map, condition, false);
/* Check if handling a regular peer and skip peer-group mechanics. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Process peer route updates. */
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("%s: Send normal update to %s for %s",
__func__, peer->host,
get_afi_safi_str(afi, safi, false));
peer_on_policy_change(peer, afi, safi, 1);
return 0;
}
/*
* Remove configuration on all peer-group members, unless they are
* explicitely overriding peer-group configuration.
*/
for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
/* Skip peers with overridden configuration. */
if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
PEER_FT_ADVERTISE_MAP))
continue;
/* Remove configuration on peer-group member. */
peer_advertise_map_filter_update(
member, afi, safi, advertise_name, advertise_map,
condition_name, condition_map, condition, false);
/* Process peer route updates. */
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("%s: Send normal update to %s for %s ",
__func__, member->host,
get_afi_safi_str(afi, safi, false));
peer_on_policy_change(member, afi, safi, 1);
}
return 0;
}
int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
uint32_t max, uint8_t threshold, int warning,
uint16_t restart, bool force)

View File

@ -682,6 +682,10 @@ struct bgp {
/* Process Queue for handling routes */
struct work_queue *process_queue;
/* BGP Conditional advertisement */
uint32_t condition_filter_count;
struct thread *t_condition_check;
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(bgp)
@ -759,6 +763,12 @@ struct bgp_nexthop {
#define BGP_GTSM_HOPS_DISABLED 0
#define BGP_GTSM_HOPS_CONNECTED 1
/* Advertise map */
#define CONDITION_NON_EXIST false
#define CONDITION_EXIST true
enum update_type { WITHDRAW, ADVERTISE };
#include "filter.h"
/* BGP filter structure. */
@ -792,6 +802,19 @@ struct bgp_filter {
char *name;
struct route_map *map;
} usmap;
/* Advertise-map */
struct {
char *aname;
struct route_map *amap;
bool condition;
char *cname;
struct route_map *cmap;
enum update_type update_type;
} advmap;
};
/* IBGP/EBGP identifier. We also have a CONFED peer, which is to say,
@ -1355,6 +1378,7 @@ struct peer {
#define PEER_FT_PREFIX_LIST (1U << 2) /* prefix-list */
#define PEER_FT_ROUTE_MAP (1U << 3) /* route-map */
#define PEER_FT_UNSUPPRESS_MAP (1U << 4) /* unsuppress-map */
#define PEER_FT_ADVERTISE_MAP (1U << 5) /* advertise-map */
/* ORF Prefix-list */
struct prefix_list *orf_plist[AFI_MAX][SAFI_MAX];
@ -1448,6 +1472,10 @@ struct peer {
/* Sender side AS path loop detection. */
bool as_path_loop_detection;
/* Conditional advertisement */
bool advmap_config_change[AFI_MAX][SAFI_MAX];
bool advmap_table_change;
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(peer)
@ -1939,11 +1967,25 @@ extern int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
const char *name,
struct route_map *route_map);
extern int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
const char *advertise_name,
struct route_map *advertise_map,
const char *condition_name,
struct route_map *condition_map,
bool condition);
extern int peer_password_set(struct peer *, const char *);
extern int peer_password_unset(struct peer *);
extern int peer_unsuppress_map_unset(struct peer *, afi_t, safi_t);
extern int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
const char *advertise_name,
struct route_map *advertise_map,
const char *condition_name,
struct route_map *condition_map,
bool condition);
extern int peer_maximum_prefix_set(struct peer *, afi_t, safi_t, uint32_t,
uint8_t, int, uint16_t, bool force);
extern int peer_maximum_prefix_unset(struct peer *, afi_t, safi_t);

View File

@ -61,6 +61,7 @@ bgpd_libbgp_a_SOURCES = \
bgpd/bgp_bfd.c \
bgpd/bgp_clist.c \
bgpd/bgp_community.c \
bgpd/bgp_conditional_adv.c \
bgpd/bgp_damp.c \
bgpd/bgp_debug.c \
bgpd/bgp_dump.c \
@ -137,6 +138,7 @@ noinst_HEADERS += \
bgpd/bgp_bfd.h \
bgpd/bgp_clist.h \
bgpd/bgp_community.h \
bgpd/bgp_conditional_adv.h \
bgpd/bgp_damp.h \
bgpd/bgp_debug.h \
bgpd/bgp_dump.h \

View File

@ -2595,6 +2595,194 @@ This makes it possible to separate not only layer 3 networks like VRF-lite netwo
Also, VRF netns based make possible to separate layer 2 networks on separate VRF
instances.
.. _bgp-conditional-advertisement:
BGP Conditional Advertisement
-----------------------------
The BGP conditional advertisement feature uses the ``non-exist-map`` or the
``exist-map`` and the ``advertise-map`` keywords of the neighbor advertise-map
command in order to track routes by the route prefix.
``non-exist-map``
1. If a route prefix is not present in the output of non-exist-map command,
then advertise the route specified by the advertise-map command.
2. If a route prefix is present in the output of non-exist-map command,
then do not advertise the route specified by the addvertise-map command.
``exist-map``
1. If a route prefix is present in the output of exist-map command,
then advertise the route specified by the advertise-map command.
2. If a route prefix is not present in the output of exist-map command,
then do not advertise the route specified by the advertise-map command.
This feature is useful when some prefixes are advertised to one of its peers
only if the information from the other peer is not present (due to failure in
peering session or partial reachability etc).
The conditional BGP announcements are sent in addition to the normal
announcements that a BGP router sends to its peer.
The conditional advertisement process is triggered by the BGP scanner process,
which runs every 60 seconds. This means that the maximum time for the conditional
advertisement to take effect is 60 seconds. The conditional advertisement can take
effect depending on when the tracked route is removed from the BGP table and
when the next instance of the BGP scanner occurs.
.. index:: [no] neighbor A.B.C.D advertise-map NAME [exist-map|non-exist-map] NAME
.. clicmd:: [no] neighbor A.B.C.D advertise-map NAME [exist-map|non-exist-map] NAME
This command enables BGP scanner process to monitor routes specified by
exist-map or non-exist-map command in BGP table and conditionally advertises
the routes specified by advertise-map command.
Sample Configuration
^^^^^^^^^^^^^^^^^^^^^
.. code-block:: frr
interface enp0s9
ip address 10.10.10.2/24
!
interface enp0s10
ip address 10.10.20.2/24
!
interface lo
ip address 203.0.113.1/32
!
router bgp 2
bgp log-neighbor-changes
no bgp ebgp-requires-policy
neighbor 10.10.10.1 remote-as 1
neighbor 10.10.20.3 remote-as 3
!
address-family ipv4 unicast
neighbor 10.10.10.1 soft-reconfiguration inbound
neighbor 10.10.20.3 soft-reconfiguration inbound
neighbor 10.10.20.3 advertise-map ADV-MAP non-exist-map EXIST-MAP
exit-address-family
!
ip prefix-list DEFAULT seq 5 permit 192.0.2.5/32
ip prefix-list DEFAULT seq 10 permit 192.0.2.1/32
ip prefix-list EXIST seq 5 permit 10.10.10.10/32
ip prefix-list DEFAULT-ROUTE seq 5 permit 0.0.0.0/0
ip prefix-list IP1 seq 5 permit 10.139.224.0/20
!
bgp community-list standard DC-ROUTES seq 5 permit 64952:3008
bgp community-list standard DC-ROUTES seq 10 permit 64671:501
bgp community-list standard DC-ROUTES seq 15 permit 64950:3009
bgp community-list standard DEFAULT-ROUTE seq 5 permit 65013:200
!
route-map ADV-MAP permit 10
match ip address prefix-list IP1
!
route-map ADV-MAP permit 20
match community DC-ROUTES
!
route-map EXIST-MAP permit 10
match community DEFAULT-ROUTE
match ip address prefix-list DEFAULT-ROUTE
!
Sample Output
^^^^^^^^^^^^^
When default route is present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2.1/32 are not advertised to R3.
.. code-block:: frr
Router2# show ip bgp
BGP table version is 20, local router ID is 203.0.113.1, vrf id 0
Default local pref 100, local AS 2
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
Network Next Hop Metric LocPrf Weight Path
*> 0.0.0.0/0 10.10.10.1 0 0 1 i
*> 10.139.224.0/20 10.10.10.1 0 0 1 ?
*> 192.0.2.1/32 10.10.10.1 0 0 1 i
*> 192.0.2.5/32 10.10.10.1 0 0 1 i
Displayed 4 routes and 4 total paths
Router2# show ip bgp neighbors 10.10.20.3
!--- Output suppressed.
For address family: IPv4 Unicast
Update group 7, subgroup 7
Packet Queue length 0
Inbound soft reconfiguration allowed
Community attribute sent to this neighbor(all)
Condition NON_EXIST, Condition-map *EXIST-MAP, Advertise-map *ADV-MAP, status: Withdraw
0 accepted prefixes
!--- Output suppressed.
Router2# show ip bgp neighbors 10.10.20.3 advertised-routes
BGP table version is 20, local router ID is 203.0.113.1, vrf id 0
Default local pref 100, local AS 2
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
Network Next Hop Metric LocPrf Weight Path
*> 0.0.0.0/0 0.0.0.0 0 1 i
*> 192.0.2.5/32 0.0.0.0 0 1 i
Total number of prefixes 2
When default route is not present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2.1/32 are advertised to R3.
.. code-block:: frr
Router2# show ip bgp
BGP table version is 21, local router ID is 203.0.113.1, vrf id 0
Default local pref 100, local AS 2
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
Network Next Hop Metric LocPrf Weight Path
*> 10.139.224.0/20 10.10.10.1 0 0 1 ?
*> 192.0.2.1/32 10.10.10.1 0 0 1 i
*> 192.0.2.5/32 10.10.10.1 0 0 1 i
Displayed 3 routes and 3 total paths
Router2# show ip bgp neighbors 10.10.20.3
!--- Output suppressed.
For address family: IPv4 Unicast
Update group 7, subgroup 7
Packet Queue length 0
Inbound soft reconfiguration allowed
Community attribute sent to this neighbor(all)
Condition NON_EXIST, Condition-map *EXIST-MAP, Advertise-map *ADV-MAP, status: Advertise
0 accepted prefixes
!--- Output suppressed.
Router2# show ip bgp neighbors 10.10.20.3 advertised-routes
BGP table version is 21, local router ID is 203.0.113.1, vrf id 0
Default local pref 100, local AS 2
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
Network Next Hop Metric LocPrf Weight Path
*> 10.139.224.0/20 0.0.0.0 0 1 ?
*> 192.0.2.1/32 0.0.0.0 0 1 i
*> 192.0.2.5/32 0.0.0.0 0 1 i
Total number of prefixes 3
Router2#
.. _bgp-debugging:
Debugging

View File

@ -0,0 +1,30 @@
!
ip prefix-list CUST seq 5 permit 10.139.224.0/20
ip prefix-list DEFAULT seq 5 permit 0.0.0.0/0
ip prefix-list PL1 seq 5 permit 192.0.2.1/32
!
route-map CUST permit 10
match ip address prefix-list CUST
set community 64671:501
!
route-map RM1 permit 10
match ip address prefix-list PL1
set community 64952:3008
!
route-map DEF permit 10
match ip address prefix-list DEFAULT
set community 64848:3011 65011:200 65013:200
!
router bgp 1
bgp log-neighbor-changes
no bgp ebgp-requires-policy
neighbor 10.10.10.2 remote-as 2
!
address-family ipv4 unicast
network 0.0.0.0/0 route-map DEF
network 192.0.2.1/32 route-map RM1
network 192.0.2.5/32
redistribute connected route-map CUST
neighbor 10.10.10.2 soft-reconfiguration inbound
exit-address-family
!

View File

@ -0,0 +1,19 @@
!
hostname Router1
!
ip route 0.0.0.0/0 blackhole
ip route 192.0.2.1/32 blackhole
ip route 192.0.2.2/32 blackhole
ip route 192.0.2.3/32 blackhole
ip route 192.0.2.4/32 blackhole
ip route 192.0.2.5/32 blackhole
!
interface r1-eth0
ip address 10.10.10.1/24
!
interface lo
ip address 10.139.224.1/20
!
ip forwarding
ipv6 forwarding
!

View File

@ -0,0 +1,44 @@
!
ip prefix-list DEFAULT seq 5 permit 192.0.2.5/32
ip prefix-list DEFAULT seq 10 permit 192.0.2.1/32
ip prefix-list EXIST seq 5 permit 10.10.10.10/32
ip prefix-list DEFAULT-ROUTE seq 5 permit 0.0.0.0/0
ip prefix-list IP1 seq 5 permit 10.139.224.0/20
ip prefix-list IP2 seq 5 permit 203.0.113.1/32
!
bgp community-list standard DC-ROUTES seq 5 permit 64952:3008
bgp community-list standard DC-ROUTES seq 10 permit 64671:501
bgp community-list standard DC-ROUTES seq 15 permit 64950:3009
bgp community-list standard DEFAULT-ROUTE seq 5 permit 65013:200
!
route-map ADV-MAP-1 permit 10
match ip address prefix-list IP1
!
route-map ADV-MAP-1 permit 20
match community DC-ROUTES
!
route-map ADV-MAP-2 permit 10
match ip address prefix-list IP2
!
route-map EXIST-MAP permit 10
match community DEFAULT-ROUTE
match ip address prefix-list DEFAULT-ROUTE
!
route-map RMAP-1 deny 10
match ip address prefix-list IP1
!
route-map RMAP-2 deny 10
match ip address prefix-list IP2
!
router bgp 2
bgp log-neighbor-changes
no bgp ebgp-requires-policy
neighbor 10.10.10.1 remote-as 1
neighbor 10.10.20.3 remote-as 3
!
address-family ipv4 unicast
network 203.0.113.1/32
neighbor 10.10.10.1 soft-reconfiguration inbound
neighbor 10.10.20.3 soft-reconfiguration inbound
exit-address-family
!

View File

@ -0,0 +1,15 @@
!
hostname Router2
!
interface r2-eth0
ip address 10.10.10.2/24
!
interface r2-eth1
ip address 10.10.20.2/24
!
interface lo
ip address 203.0.113.1/32
!
ip forwarding
ipv6 forwarding
!

View File

@ -0,0 +1,11 @@
!
router bgp 3
bgp log-neighbor-changes
no bgp ebgp-requires-policy
neighbor 10.10.20.2 remote-as 2
!
address-family ipv4 unicast
neighbor 10.10.20.2 soft-reconfiguration inbound
exit-address-family
!

View File

@ -0,0 +1,12 @@
!
hostname Router3
!
interface r3-eth0
ip address 10.10.20.3/24
!
interface lo
ip address 198.51.100.1/32
!
ip forwarding
ipv6 forwarding
!

View File

@ -0,0 +1,961 @@
#!/usr/bin/env python
#
# test_bgp_conditional_advertisement.py
#
# Copyright (c) 2020 by
# Samsung R&D Institute India - Bangalore.
# Madhurilatha Kuruganti
#
# Permission to use, copy, modify, and/or distribute this software
# for any purpose with or without fee is hereby granted, provided
# that the above copyright notice and this permission notice appear
# in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
# OF THIS SOFTWARE.
#
"""
Test BGP conditional advertisement functionality.
+--------+ +--------+ +--------+
| | | | | |
| R1 |------------| R2 |------------| R3 |
| | | | | |
+--------+ +--------+ +--------+
R2 is DUT and peers with R1 and R3 in default bgp instance.
Following tests are covered under BGP conditional advertisement functionality.
Conditional advertisement
-------------------------
TC11: R3 BGP convergence, without advertise-map configuration.
All routes are advertised to R3.
TC21: exist-map routes present in R2's BGP table.
advertise-map routes present in R2's BGP table are advertised to R3.
TC22: exist-map routes not present in R2's BGP table
advertise-map routes present in R2's BGP table are withdrawn from R3.
TC31: non-exist-map routes not present in R2's BGP table
advertise-map routes present in R2's BGP table are advertised to R3.
TC32: non-exist-map routes present in R2's BGP table
advertise-map routes present in R2's BGP table are withdrawn from R3.
TC41: non-exist-map route-map configuration removed in R2.
advertise-map routes present in R2's BGP table are advertised to R3.
TC42: exist-map route-map configuration removed in R2
advertise-map routes present in R2's BGP table are withdrawn from R3.
Conditional advertisement(received routes) along with Route-map Filter
----------------------------------------------------------------------
TC51: exist-map routes present in R2's BGP table, with route-map filter.
All routes are withdrawn from R3 except advertise-map routes.
TC52: exist-map routes present in R2's BGP table, without route-map filter.
All routes are advertised to R3 including advertise-map routes.
TC53: non-exist-map routes present in R2's BGP table, with route-map filter.
All routes are withdrawn from R3 including advertise-map routes.
TC54: non-exist-map routes present in R2's BGP table, without route-map filter.
All routes are advertised to R3 except advertise-map routes.
TC61: exist-map routes not present in R2's BGP table, with route-map filter.
All routes are withdrawn from R3 including advertise-map routes.
TC62: exist-map routes not present in R2's BGP table, without route-map filter.
All routes are advertised to R3 except advertise-map routes.
TC63: non-exist-map routes not present in R2's BGP table, with route-map filter.
All routes are withdrawn from R3 except advertise-map routes.
TC64: non-exist-map routes not present in R2's BGP table, without route-map filter.
All routes are advertised to R3 including advertise-map routes.
Conditional advertisement(attached routes) along with Route-map Filter
-----------------------------------------------------------------
TC71: exist-map routes present in R2's BGP table, with route-map filter.
All routes are withdrawn from R3 except advertise-map routes.
TC72: exist-map routes present in R2's BGP table, without route-map filter.
All routes are advertised to R3 including advertise-map routes.
TC73: non-exist-map routes present in R2's BGP table, with route-map filter.
All routes are withdrawn from R3 including advertise-map routes.
TC74: non-exist-map routes present in R2's BGP table, without route-map filter.
All routes are advertised to R3 except advertise-map routes.
TC81: exist-map routes not present in R2's BGP table, with route-map filter.
All routes are withdrawn from R3 including advertise-map routes.
TC82: exist-map routes not present in R2's BGP table, without route-map filter.
All routes are advertised to R3 except advertise-map routes.
TC83: non-exist-map routes not present in R2's BGP table, with route-map filter.
All routes are withdrawn from R3 except advertise-map routes.
TC84: non-exist-map routes not present in R2's BGP table, without route-map filter.
All routes are advertised to R3 including advertise-map routes.
TC91: exist-map routes present in R2's BGP table, with route-map filter and network.
All routes are advertised to R3 including advertise-map routes.
TC92: exist-map routes present in R2's BGP table, with route-map filter and no network.
All routes are advertised to R3 except advertise-map routes.
TC93: non-exist-map routes not present in R2's BGP table, with route-map filter and network.
All routes are advertised to R3 including advertise-map routes.
TC94: non-exist-map routes not present in R2's BGP table, with route-map filter and no network.
All routes are advertised to R3 except advertise-map routes.
i.e.
+----------------+-------------------------+------------------------+
| Routes in | exist-map status | advertise-map status |
| BGP table | | |
+----------------+-------------------------+------------------------+
| Present | Condition matched | Advertise |
+----------------+-------------------------+------------------------+
| Not Present | Condition not matched | Withdrawn |
+----------------+-------------------------+------------------------+
| | non-exist-map status | advertise-map status |
| | | |
+----------------+-------------------------+------------------------+
| Present | Condition matched | Withdrawn |
+----------------+-------------------------+------------------------+
| Not Present | Condition not matched | Advertise |
+----------------+-------------------------+------------------------+
Here in this topology, based on the default route presence in R2 and
the configured condition-map (exist-map/non-exist-map) 10.139.224.0/20
will be either advertised/withdrawn to/from R3.
"""
import os
import sys
import json
import time
import pytest
import functools
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from mininet.topo import Topo
class BgpConditionalAdvertisementTopo(Topo):
def build(self, *_args, **_opts):
tgen = get_topogen(self)
r1 = tgen.add_router("r1")
r2 = tgen.add_router("r2")
r3 = tgen.add_router("r3")
switch = tgen.add_switch("s1")
switch.add_link(r1)
switch.add_link(r2)
switch = tgen.add_switch("s2")
switch.add_link(r2)
switch.add_link(r3)
def setup_module(mod):
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
logger.info("=" * 40)
logger.info("Running setup_module to create topology")
tgen = Topogen(BgpConditionalAdvertisementTopo, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
for i, (rname, router) in enumerate(router_list.items(), 1):
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
router.load_config(
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
)
tgen.start_router()
logger.info("Running setup_module() done")
def teardown_module(mod):
"""
Teardown the pytest environment
* `mod`: module name
"""
logger.info("Running teardown_module to delete topology")
tgen = get_topogen()
tgen.stop_topology()
logger.info(
"Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
)
logger.info("=" * 40)
def test_bgp_conditional_advertisement():
"""
Test BGP conditional advertisement functionality.
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router1 = tgen.gears["r1"]
router2 = tgen.gears["r2"]
router3 = tgen.gears["r3"]
passed = "PASSED!!!"
failed = "FAILED!!!"
def _all_routes_advertised(router):
output = json.loads(router.vtysh_cmd("show ip route json"))
expected = {
"0.0.0.0/0": [{"protocol": "bgp"}],
"192.0.2.1/32": [{"protocol": "bgp"}],
"192.0.2.5/32": [{"protocol": "bgp"}],
"10.139.224.0/20": [{"protocol": "bgp"}],
"203.0.113.1/32": [{"protocol": "bgp"}],
}
return topotest.json_cmp(output, expected)
def _all_routes_withdrawn(router):
output = json.loads(router.vtysh_cmd("show ip route json"))
expected = {
"0.0.0.0/0": None,
"192.0.2.1/32": None,
"192.0.2.5/32": None,
"10.139.224.0/20": None,
"203.0.113.1/32": None,
}
return topotest.json_cmp(output, expected)
# BGP conditional advertisement with route-maps
# EXIST-MAP, ADV-MAP-1 and RMAP-1
def _exist_map_routes_present(router):
return _all_routes_advertised(router)
def _exist_map_routes_not_present(router):
output = json.loads(router.vtysh_cmd("show ip route json"))
expected = {
"0.0.0.0/0": None,
"192.0.2.1/32": None,
"192.0.2.5/32": [{"protocol": "bgp"}],
"10.139.224.0/20": None,
"203.0.113.1/32": [{"protocol": "bgp"}],
}
return topotest.json_cmp(output, expected)
def _non_exist_map_routes_present(router):
output = json.loads(router.vtysh_cmd("show ip route json"))
expected = {
"0.0.0.0/0": [{"protocol": "bgp"}],
"192.0.2.1/32": None,
"192.0.2.5/32": [{"protocol": "bgp"}],
"10.139.224.0/20": None,
"203.0.113.1/32": [{"protocol": "bgp"}],
}
return topotest.json_cmp(output, expected)
def _non_exist_map_routes_not_present(router):
output = json.loads(router.vtysh_cmd("show ip route json"))
expected = {
"0.0.0.0/0": None,
"192.0.2.1/32": [{"protocol": "bgp"}],
"192.0.2.5/32": [{"protocol": "bgp"}],
"10.139.224.0/20": [{"protocol": "bgp"}],
"203.0.113.1/32": [{"protocol": "bgp"}],
}
return topotest.json_cmp(output, expected)
def _exist_map_no_condition_route_map(router):
return _non_exist_map_routes_present(router)
def _non_exist_map_no_condition_route_map(router):
return _all_routes_advertised(router)
def _exist_map_routes_present_rmap_filter(router):
output = json.loads(router.vtysh_cmd("show ip route json"))
expected = {
"0.0.0.0/0": None,
"192.0.2.1/32": [{"protocol": "bgp"}],
"192.0.2.5/32": None,
"10.139.224.0/20": [{"protocol": "bgp"}],
"203.0.113.1/32": None,
}
return topotest.json_cmp(output, expected)
def _exist_map_routes_present_no_rmap_filter(router):
return _all_routes_advertised(router)
def _non_exist_map_routes_present_rmap_filter(router):
return _all_routes_withdrawn(router)
def _non_exist_map_routes_present_no_rmap_filter(router):
return _non_exist_map_routes_present(router)
def _exist_map_routes_not_present_rmap_filter(router):
return _all_routes_withdrawn(router)
def _exist_map_routes_not_present_no_rmap_filter(router):
return _exist_map_routes_not_present(router)
def _non_exist_map_routes_not_present_rmap_filter(router):
return _exist_map_routes_present_rmap_filter(router)
def _non_exist_map_routes_not_present_no_rmap_filter(router):
return _non_exist_map_routes_not_present(router)
# BGP conditional advertisement with route-maps
# EXIST-MAP, ADV-MAP-2 and RMAP-2
def _exist_map_routes_not_present_rmap2_filter(router):
return _all_routes_withdrawn(router)
def _exist_map_routes_not_present_no_rmap2_filter(router):
output = json.loads(router.vtysh_cmd("show ip route json"))
expected = {
"0.0.0.0/0": None,
"192.0.2.1/32": [{"protocol": "bgp"}],
"192.0.2.5/32": [{"protocol": "bgp"}],
"10.139.224.0/20": [{"protocol": "bgp"}],
"203.0.113.1/32": None,
}
return topotest.json_cmp(output, expected)
def _non_exist_map_routes_not_present_rmap2_filter(router):
output = json.loads(router.vtysh_cmd("show ip route json"))
expected = {
"0.0.0.0/0": None,
"192.0.2.1/32": None,
"192.0.2.5/32": None,
"10.139.224.0/20": None,
"203.0.113.1/32": [{"protocol": "bgp"}],
}
return topotest.json_cmp(output, expected)
def _non_exist_map_routes_not_present_no_rmap2_filter(router):
return _non_exist_map_routes_not_present(router)
def _exist_map_routes_present_rmap2_filter(router):
return _non_exist_map_routes_not_present_rmap2_filter(router)
def _exist_map_routes_present_no_rmap2_filter(router):
return _all_routes_advertised(router)
def _non_exist_map_routes_present_rmap2_filter(router):
return _all_routes_withdrawn(router)
def _non_exist_map_routes_present_no_rmap2_filter(router):
output = json.loads(router.vtysh_cmd("show ip route json"))
expected = {
"0.0.0.0/0": [{"protocol": "bgp"}],
"192.0.2.1/32": [{"protocol": "bgp"}],
"192.0.2.5/32": [{"protocol": "bgp"}],
"10.139.224.0/20": [{"protocol": "bgp"}],
"203.0.113.1/32": None,
}
return topotest.json_cmp(output, expected)
def _exist_map_routes_present_rmap2_network(router):
return _non_exist_map_routes_not_present_rmap2_filter(router)
def _exist_map_routes_present_rmap2_no_network(router):
return _all_routes_withdrawn(router)
def _non_exist_map_routes_not_present_rmap2_network(router):
return _non_exist_map_routes_not_present_rmap2_filter(router)
def _non_exist_map_routes_not_present_rmap2_no_network(router):
return _all_routes_withdrawn(router)
# TC11: R3 BGP convergence, without advertise-map configuration.
# All routes are advertised to R3.
test_func = functools.partial(_all_routes_advertised, router3)
success, result = topotest.run_and_expect(test_func, None, count=130, wait=1)
msg = 'TC11: "router3" BGP convergence - '
assert result is None, msg + failed
logger.info(msg + passed)
# TC21: exist-map routes present in R2's BGP table.
# advertise-map routes present in R2's BGP table are advertised to R3.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 advertise-map ADV-MAP-1 exist-map EXIST-MAP
"""
)
test_func = functools.partial(_exist_map_routes_present, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC21: exist-map routes present in "router2" BGP table - '
assert result is None, msg + failed
logger.info(msg + passed)
# TC22: exist-map routes not present in R2's BGP table
# advertise-map routes present in R2's BGP table are withdrawn from R3.
router1.vtysh_cmd(
"""
configure terminal
router bgp 1
address-family ipv4 unicast
no network 0.0.0.0/0 route-map DEF
"""
)
test_func = functools.partial(_exist_map_routes_not_present, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC22: exist-map routes not present in "router2" BGP table - '
assert result is None, msg + failed
logger.info(msg + passed)
# TC31: non-exist-map routes not present in R2's BGP table
# advertise-map routes present in R2's BGP table are advertised to R3.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 advertise-map ADV-MAP-1 non-exist-map EXIST-MAP
"""
)
test_func = functools.partial(_non_exist_map_routes_not_present, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC31: non-exist-map routes not present in "router2" BGP table - '
assert result is None, msg + failed
logger.info(msg + passed)
# TC32: non-exist-map routes present in R2's BGP table
# advertise-map routes present in R2's BGP table are withdrawn from R3.
router1.vtysh_cmd(
"""
configure terminal
router bgp 1
address-family ipv4 unicast
network 0.0.0.0/0 route-map DEF
"""
)
test_func = functools.partial(_non_exist_map_routes_present, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC32: non-exist-map routes present in "router2" BGP table - '
assert result is None, msg + failed
logger.info(msg + passed)
# TC41: non-exist-map route-map configuration removed in R2.
# advertise-map routes present in R2's BGP table are advertised to R3.
router2.vtysh_cmd(
"""
configure terminal
no route-map EXIST-MAP permit 10
"""
)
test_func = functools.partial(_non_exist_map_no_condition_route_map, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC41: non-exist-map route-map removed in "router2" - '
assert result is None, msg + failed
logger.info(msg + passed)
# TC42: exist-map route-map configuration removed in R2
# advertise-map routes present in R2's BGP table are withdrawn from R3.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 advertise-map ADV-MAP-1 exist-map EXIST-MAP
"""
)
test_func = functools.partial(_exist_map_no_condition_route_map, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = 'TC42: exist-map route-map removed in "router2" - '
assert result is None, msg + failed
logger.info(msg + passed)
# TC51: exist-map routes present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 except advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
route-map EXIST-MAP permit 10
match community DEFAULT-ROUTE
match ip address prefix-list DEFAULT-ROUTE
!
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 route-map RMAP-1 out
"""
)
test_func = functools.partial(_exist_map_routes_present_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC51: exist-map routes present with route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC52: exist-map routes present in R2's BGP table, no route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no neighbor 10.10.20.3 route-map RMAP-1 out
"""
)
test_func = functools.partial(_exist_map_routes_present_no_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC52: exist-map routes present, no route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC53: non-exist-map routes present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 including advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 route-map RMAP-1 out
neighbor 10.10.20.3 advertise-map ADV-MAP-1 non-exist-map EXIST-MAP
"""
)
test_func = functools.partial(_non_exist_map_routes_present_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC53: non-exist-map routes present, with route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC54: non-exist-map routes present in R2's BGP table, no route-map filter.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no neighbor 10.10.20.3 route-map RMAP-1 out
"""
)
test_func = functools.partial(_non_exist_map_routes_present_no_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC54: non-exist-map routes present, no route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC61: exist-map routes not present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 including advertise-map routes.
router1.vtysh_cmd(
"""
configure terminal
router bgp 1
address-family ipv4 unicast
no network 0.0.0.0/0 route-map DEF
"""
)
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 route-map RMAP-1 out
neighbor 10.10.20.3 advertise-map ADV-MAP-1 exist-map EXIST-MAP
"""
)
test_func = functools.partial(_exist_map_routes_not_present_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC61: exist-map routes not present, route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC62: exist-map routes not present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no neighbor 10.10.20.3 route-map RMAP-1 out
"""
)
test_func = functools.partial(_exist_map_routes_not_present_no_rmap_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC62: exist-map routes not present, no route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC63: non-exist-map routes not present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 except advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 route-map RMAP-1 out
neighbor 10.10.20.3 advertise-map ADV-MAP-1 non-exist-map EXIST-MAP
"""
)
test_func = functools.partial(
_non_exist_map_routes_not_present_rmap_filter, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC63: non-exist-map routes not present, route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC64: non-exist-map routes not present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no neighbor 10.10.20.3 route-map RMAP-1 out
"""
)
test_func = functools.partial(
_non_exist_map_routes_not_present_no_rmap_filter, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC64: non-exist-map routes not present, no route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC71: exist-map routes present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 except advertise-map routes.
router1.vtysh_cmd(
"""
configure terminal
router bgp 1
address-family ipv4 unicast
network 0.0.0.0/0 route-map DEF
"""
)
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 route-map RMAP-2 out
neighbor 10.10.20.3 advertise-map ADV-MAP-2 exist-map EXIST-MAP
"""
)
test_func = functools.partial(_exist_map_routes_present_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC71: exist-map routes present, route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC72: exist-map routes present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no neighbor 10.10.20.3 route-map RMAP-2 out
"""
)
test_func = functools.partial(_exist_map_routes_present_no_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC72: exist-map routes present, no route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC73: non-exist-map routes present in R2's BGP table, with route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 route-map RMAP-2 out
neighbor 10.10.20.3 advertise-map ADV-MAP-2 non-exist-map EXIST-MAP
"""
)
test_func = functools.partial(_non_exist_map_routes_present_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC73: non-exist-map routes present, route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC74: non-exist-map routes present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no neighbor 10.10.20.3 route-map RMAP-2 out
"""
)
test_func = functools.partial(
_non_exist_map_routes_present_no_rmap2_filter, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC74: non-exist-map routes present, no route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC81: exist-map routes not present in R2's BGP table, with route-map filter.
# All routes are withdrawn from R3 including advertise-map routes.
router1.vtysh_cmd(
"""
configure terminal
router bgp 1
address-family ipv4 unicast
no network 0.0.0.0/0 route-map DEF
"""
)
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 route-map RMAP-2 out
neighbor 10.10.20.3 advertise-map ADV-MAP-2 exist-map EXIST-MAP
"""
)
test_func = functools.partial(_exist_map_routes_not_present_rmap2_filter, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC81: exist-map routes not present, route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC82: exist-map routes not present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no neighbor 10.10.20.3 route-map RMAP-2 out
"""
)
test_func = functools.partial(
_exist_map_routes_not_present_no_rmap2_filter, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC82: exist-map routes not present, no route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC83: non-exist-map routes not present in R2's BGP table, with route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 route-map RMAP-2 out
neighbor 10.10.20.3 advertise-map ADV-MAP-2 non-exist-map EXIST-MAP
"""
)
test_func = functools.partial(
_non_exist_map_routes_not_present_rmap2_filter, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC83: non-exist-map routes not present, route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC84: non-exist-map routes not present in R2's BGP table, without route-map filter.
# All routes are advertised to R3 including advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no neighbor 10.10.20.3 route-map RMAP-2 out
"""
)
test_func = functools.partial(
_non_exist_map_routes_not_present_no_rmap2_filter, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC84: non-exist-map routes not present, no route-map filter - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC91: exist-map routes present in R2's BGP table, with route-map filter and network.
# All routes are advertised to R3 including advertise-map routes.
router1.vtysh_cmd(
"""
configure terminal
router bgp 1
address-family ipv4 unicast
network 0.0.0.0/0 route-map DEF
"""
)
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
neighbor 10.10.20.3 route-map RMAP-2 out
neighbor 10.10.20.3 advertise-map ADV-MAP-2 exist-map EXIST-MAP
"""
)
test_func = functools.partial(_exist_map_routes_present_rmap2_network, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC91: exist-map routes present, route-map filter and network - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC92: exist-map routes present in R2's BGP table, with route-map filter and no network.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no network 203.0.113.1/32
"""
)
test_func = functools.partial(_exist_map_routes_present_rmap2_no_network, router3)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC92: exist-map routes present, route-map filter and no network - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC93: non-exist-map routes not present in R2's BGP table, with route-map filter and network.
# All routes are advertised to R3 including advertise-map routes.
router1.vtysh_cmd(
"""
configure terminal
router bgp 1
address-family ipv4 unicast
no network 0.0.0.0/0 route-map DEF
"""
)
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
network 203.0.113.1/32
neighbor 10.10.20.3 advertise-map ADV-MAP-2 non-exist-map EXIST-MAP
"""
)
test_func = functools.partial(
_non_exist_map_routes_not_present_rmap2_network, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC93: non-exist-map routes not present, route-map filter and network - "
assert result is None, msg + failed
logger.info(msg + passed)
# TC94: non-exist-map routes not present in R2's BGP table, with route-map filter and no network.
# All routes are advertised to R3 except advertise-map routes.
router2.vtysh_cmd(
"""
configure terminal
router bgp 2
address-family ipv4 unicast
no network 203.0.113.1/32
"""
)
test_func = functools.partial(
_non_exist_map_routes_not_present_rmap2_no_network, router3
)
success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
msg = "TC94: non-exist-map routes not present, route-map filter and no network - "
assert result is None, msg + failed
logger.info(msg + passed)
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
if not tgen.is_memleak_enabled():
pytest.skip("Memory leak test/report is disabled")
tgen.report_memory_leaks()
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))