mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 07:23:41 +00:00
Merge pull request #7189 from maduri111/bgpd-conditional-adv
bgpd: conditional advertisement
This commit is contained in:
commit
7f2f38c62f
343
bgpd/bgp_conditional_adv.c
Normal file
343
bgpd/bgp_conditional_adv.c
Normal 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);
|
||||||
|
}
|
47
bgpd/bgp_conditional_adv.h
Normal file
47
bgpd/bgp_conditional_adv.h
Normal 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 */
|
@ -1783,6 +1783,9 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
|
|||||||
|
|
||||||
peer->update_time = bgp_clock();
|
peer->update_time = bgp_clock();
|
||||||
|
|
||||||
|
/* Notify BGP Conditional advertisement scanner process */
|
||||||
|
peer->advmap_table_change = true;
|
||||||
|
|
||||||
return Receive_UPDATE_message;
|
return Receive_UPDATE_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
|
||||||
{
|
{
|
||||||
if (family == AF_INET) {
|
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,
|
bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
|
||||||
struct update_subgroup *subgrp,
|
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 bgp_filter *filter;
|
||||||
struct peer *from;
|
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);
|
bgp_peer_as_override(bgp, afi, safi, peer, attr);
|
||||||
|
|
||||||
/* Route map & unsuppress-map apply. */
|
/* 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 rmap_path = {0};
|
||||||
struct bgp_path_info_extra dummy_rmap_path_extra = {0};
|
struct bgp_path_info_extra dummy_rmap_path_extra = {0};
|
||||||
struct attr dummy_attr = {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.
|
/* Announcement to the subgroup. If the route is filtered withdraw it.
|
||||||
*/
|
*/
|
||||||
if (selected) {
|
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);
|
bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
|
||||||
else
|
else
|
||||||
bgp_adj_out_unset_subgroup(dest, subgrp, 1,
|
bgp_adj_out_unset_subgroup(dest, subgrp, 1,
|
||||||
@ -4360,6 +4390,10 @@ static int bgp_announce_route_timer_expired(struct thread *t)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
peer_af_announce_route(paf, 1);
|
peer_af_announce_route(paf, 1);
|
||||||
|
|
||||||
|
/* Notify BGP conditional advertisement scanner percess */
|
||||||
|
peer->advmap_config_change[paf->afi][paf->safi] = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,6 +454,14 @@ struct bgp_aggregate {
|
|||||||
#define UNSUPPRESS_MAP_NAME(F) ((F)->usmap.name)
|
#define UNSUPPRESS_MAP_NAME(F) ((F)->usmap.name)
|
||||||
#define UNSUPPRESS_MAP(F) ((F)->usmap.map)
|
#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) */
|
/* path PREFIX (addpath rxid NUMBER) */
|
||||||
#define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32
|
#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,
|
struct bgp_path_info *path, int display,
|
||||||
json_object *json);
|
json_object *json);
|
||||||
|
|
||||||
|
extern void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp);
|
||||||
|
|
||||||
extern void subgroup_process_announce_selected(struct update_subgroup *subgrp,
|
extern void subgroup_process_announce_selected(struct update_subgroup *subgrp,
|
||||||
struct bgp_path_info *selected,
|
struct bgp_path_info *selected,
|
||||||
struct bgp_dest *dest,
|
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,
|
extern bool subgroup_announce_check(struct bgp_dest *dest,
|
||||||
struct bgp_path_info *pi,
|
struct bgp_path_info *pi,
|
||||||
struct update_subgroup *subgrp,
|
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_peer_clear_node_queue_drain_immediate(struct peer *peer);
|
||||||
extern void bgp_process_queues_drain_immediate(void);
|
extern void bgp_process_queues_drain_immediate(void);
|
||||||
|
@ -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))
|
if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
|
||||||
filter->usmap.map = map;
|
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
|
if (peer->default_rmap[afi][safi].name
|
||||||
&& (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
|
&& (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
|
||||||
peer->default_rmap[afi][safi].map = map;
|
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,
|
static void bgp_route_map_update_peer_group(const char *rmap_name,
|
||||||
|
@ -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));
|
MTYPE_BGP_FILTER_NAME, UNSUPPRESS_MAP_NAME(srcfilter));
|
||||||
UNSUPPRESS_MAP(dstfilter) = UNSUPPRESS_MAP(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->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);
|
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),
|
strlen(filter->usmap.name), SEED1),
|
||||||
key);
|
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)
|
if (peer->default_rmap[afi][safi].name)
|
||||||
key = jhash_1word(
|
key = jhash_1word(
|
||||||
jhash(peer->default_rmap[afi][safi].name,
|
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)))
|
&& strcmp(fl1->usmap.name, fl2->usmap.name)))
|
||||||
return false;
|
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
|
if ((pe1->default_rmap[afi][safi].name
|
||||||
&& !pe2->default_rmap[afi][safi].name)
|
&& !pe2->default_rmap[afi][safi].name)
|
||||||
|| (!pe1->default_rmap[afi][safi].name
|
|| (!pe1->default_rmap[afi][safi].name
|
||||||
|
@ -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;
|
return UPDWALK_CONTINUE;
|
||||||
@ -642,7 +645,8 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
|
|||||||
peer->addpath_type[afi][safi],
|
peer->addpath_type[afi][safi],
|
||||||
ri))) {
|
ri))) {
|
||||||
if (subgroup_announce_check(dest, ri, subgrp,
|
if (subgroup_announce_check(dest, ri, subgrp,
|
||||||
dest_p, &attr))
|
dest_p, &attr,
|
||||||
|
false))
|
||||||
bgp_adj_out_set_subgroup(dest, subgrp,
|
bgp_adj_out_set_subgroup(dest, subgrp,
|
||||||
&attr, ri);
|
&attr, ri);
|
||||||
else {
|
else {
|
||||||
@ -827,7 +831,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
|
|||||||
if (subgroup_announce_check(
|
if (subgroup_announce_check(
|
||||||
dest, pi, subgrp,
|
dest, pi, subgrp,
|
||||||
bgp_dest_get_prefix(dest),
|
bgp_dest_get_prefix(dest),
|
||||||
&attr))
|
&attr, false))
|
||||||
bgp_adj_out_set_subgroup(
|
bgp_adj_out_set_subgroup(
|
||||||
dest, subgrp, &attr,
|
dest, subgrp, &attr,
|
||||||
pi);
|
pi);
|
||||||
|
124
bgpd/bgp_vty.c
124
bgpd/bgp_vty.c
@ -7175,6 +7175,68 @@ ALIAS_HIDDEN(no_neighbor_filter_list, no_neighbor_filter_list_hidden_cmd,
|
|||||||
"Filter incoming routes\n"
|
"Filter incoming routes\n"
|
||||||
"Filter outgoing 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. */
|
/* Set route-map to the peer. */
|
||||||
static int peer_route_map_set_vty(struct vty *vty, const char *ip_str,
|
static int peer_route_map_set_vty(struct vty *vty, const char *ip_str,
|
||||||
afi_t afi, safi_t safi, const char *name_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_prefA = NULL;
|
||||||
json_object *json_prefB = NULL;
|
json_object *json_prefB = NULL;
|
||||||
json_object *json_addr = NULL;
|
json_object *json_addr = NULL;
|
||||||
|
json_object *json_advmap = NULL;
|
||||||
|
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
json_addr = json_object_new_object();
|
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",
|
"selectiveUnsuppressRouteMap",
|
||||||
filter->usmap.name);
|
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 */
|
/* Receive prefix count */
|
||||||
json_object_int_add(json_addr, "acceptedPrefixCounter",
|
json_object_int_add(json_addr, "acceptedPrefixCounter",
|
||||||
p->pcount[afi][safi]);
|
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.map ? "*" : "",
|
||||||
filter->usmap.name);
|
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 */
|
/* Receive prefix count */
|
||||||
vty_out(vty, " %u accepted prefixes\n",
|
vty_out(vty, " %u accepted prefixes\n",
|
||||||
p->pcount[afi][safi]);
|
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);
|
return !!(filter->map[direct].name);
|
||||||
case PEER_FT_UNSUPPRESS_MAP:
|
case PEER_FT_UNSUPPRESS_MAP:
|
||||||
return !!(filter->usmap.name);
|
return !!(filter->usmap.name);
|
||||||
|
case PEER_FT_ADVERTISE_MAP:
|
||||||
|
return !!(filter->advmap.aname
|
||||||
|
&& ((filter->advmap.condition == direct)
|
||||||
|
&& filter->advmap.cname));
|
||||||
default:
|
default:
|
||||||
return false;
|
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,
|
vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
|
||||||
filter->usmap.name);
|
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. */
|
/* filter-list. */
|
||||||
if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
|
if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
|
||||||
FILTER_IN))
|
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, &neighbor_unsuppress_map_cmd);
|
||||||
install_element(BGP_VPNV6_NODE, &no_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. */
|
/* neighbor maximum-prefix-out commands. */
|
||||||
install_element(BGP_NODE, &neighbor_maximum_prefix_out_cmd);
|
install_element(BGP_NODE, &neighbor_maximum_prefix_out_cmd);
|
||||||
install_element(BGP_NODE, &no_neighbor_maximum_prefix_out_cmd);
|
install_element(BGP_NODE, &no_neighbor_maximum_prefix_out_cmd);
|
||||||
|
167
bgpd/bgpd.c
167
bgpd/bgpd.c
@ -54,6 +54,7 @@
|
|||||||
#include "bgpd/bgp_debug.h"
|
#include "bgpd/bgp_debug.h"
|
||||||
#include "bgpd/bgp_errors.h"
|
#include "bgpd/bgp_errors.h"
|
||||||
#include "bgpd/bgp_community.h"
|
#include "bgpd/bgp_community.h"
|
||||||
|
#include "bgpd/bgp_conditional_adv.h"
|
||||||
#include "bgpd/bgp_attr.h"
|
#include "bgpd/bgp_attr.h"
|
||||||
#include "bgpd/bgp_regex.h"
|
#include "bgpd/bgp_regex.h"
|
||||||
#include "bgpd/bgp_clist.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;
|
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,
|
int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||||
uint32_t max, uint8_t threshold, int warning,
|
uint32_t max, uint8_t threshold, int warning,
|
||||||
uint16_t restart, bool force)
|
uint16_t restart, bool force)
|
||||||
|
42
bgpd/bgpd.h
42
bgpd/bgpd.h
@ -682,6 +682,10 @@ struct bgp {
|
|||||||
/* Process Queue for handling routes */
|
/* Process Queue for handling routes */
|
||||||
struct work_queue *process_queue;
|
struct work_queue *process_queue;
|
||||||
|
|
||||||
|
/* BGP Conditional advertisement */
|
||||||
|
uint32_t condition_filter_count;
|
||||||
|
struct thread *t_condition_check;
|
||||||
|
|
||||||
QOBJ_FIELDS
|
QOBJ_FIELDS
|
||||||
};
|
};
|
||||||
DECLARE_QOBJ_TYPE(bgp)
|
DECLARE_QOBJ_TYPE(bgp)
|
||||||
@ -759,6 +763,12 @@ struct bgp_nexthop {
|
|||||||
#define BGP_GTSM_HOPS_DISABLED 0
|
#define BGP_GTSM_HOPS_DISABLED 0
|
||||||
#define BGP_GTSM_HOPS_CONNECTED 1
|
#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"
|
#include "filter.h"
|
||||||
|
|
||||||
/* BGP filter structure. */
|
/* BGP filter structure. */
|
||||||
@ -792,6 +802,19 @@ struct bgp_filter {
|
|||||||
char *name;
|
char *name;
|
||||||
struct route_map *map;
|
struct route_map *map;
|
||||||
} usmap;
|
} 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,
|
/* 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_PREFIX_LIST (1U << 2) /* prefix-list */
|
||||||
#define PEER_FT_ROUTE_MAP (1U << 3) /* route-map */
|
#define PEER_FT_ROUTE_MAP (1U << 3) /* route-map */
|
||||||
#define PEER_FT_UNSUPPRESS_MAP (1U << 4) /* unsuppress-map */
|
#define PEER_FT_UNSUPPRESS_MAP (1U << 4) /* unsuppress-map */
|
||||||
|
#define PEER_FT_ADVERTISE_MAP (1U << 5) /* advertise-map */
|
||||||
|
|
||||||
/* ORF Prefix-list */
|
/* ORF Prefix-list */
|
||||||
struct prefix_list *orf_plist[AFI_MAX][SAFI_MAX];
|
struct prefix_list *orf_plist[AFI_MAX][SAFI_MAX];
|
||||||
@ -1448,6 +1472,10 @@ struct peer {
|
|||||||
/* Sender side AS path loop detection. */
|
/* Sender side AS path loop detection. */
|
||||||
bool 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
|
QOBJ_FIELDS
|
||||||
};
|
};
|
||||||
DECLARE_QOBJ_TYPE(peer)
|
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,
|
const char *name,
|
||||||
struct route_map *route_map);
|
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_set(struct peer *, const char *);
|
||||||
extern int peer_password_unset(struct peer *);
|
extern int peer_password_unset(struct peer *);
|
||||||
|
|
||||||
extern int peer_unsuppress_map_unset(struct peer *, afi_t, safi_t);
|
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,
|
extern int peer_maximum_prefix_set(struct peer *, afi_t, safi_t, uint32_t,
|
||||||
uint8_t, int, uint16_t, bool force);
|
uint8_t, int, uint16_t, bool force);
|
||||||
extern int peer_maximum_prefix_unset(struct peer *, afi_t, safi_t);
|
extern int peer_maximum_prefix_unset(struct peer *, afi_t, safi_t);
|
||||||
|
@ -61,6 +61,7 @@ bgpd_libbgp_a_SOURCES = \
|
|||||||
bgpd/bgp_bfd.c \
|
bgpd/bgp_bfd.c \
|
||||||
bgpd/bgp_clist.c \
|
bgpd/bgp_clist.c \
|
||||||
bgpd/bgp_community.c \
|
bgpd/bgp_community.c \
|
||||||
|
bgpd/bgp_conditional_adv.c \
|
||||||
bgpd/bgp_damp.c \
|
bgpd/bgp_damp.c \
|
||||||
bgpd/bgp_debug.c \
|
bgpd/bgp_debug.c \
|
||||||
bgpd/bgp_dump.c \
|
bgpd/bgp_dump.c \
|
||||||
@ -137,6 +138,7 @@ noinst_HEADERS += \
|
|||||||
bgpd/bgp_bfd.h \
|
bgpd/bgp_bfd.h \
|
||||||
bgpd/bgp_clist.h \
|
bgpd/bgp_clist.h \
|
||||||
bgpd/bgp_community.h \
|
bgpd/bgp_community.h \
|
||||||
|
bgpd/bgp_conditional_adv.h \
|
||||||
bgpd/bgp_damp.h \
|
bgpd/bgp_damp.h \
|
||||||
bgpd/bgp_debug.h \
|
bgpd/bgp_debug.h \
|
||||||
bgpd/bgp_dump.h \
|
bgpd/bgp_dump.h \
|
||||||
|
188
doc/user/bgp.rst
188
doc/user/bgp.rst
@ -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
|
Also, VRF netns based make possible to separate layer 2 networks on separate VRF
|
||||||
instances.
|
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:
|
.. _bgp-debugging:
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
|
30
tests/topotests/bgp_conditional_advertisement/r1/bgpd.conf
Normal file
30
tests/topotests/bgp_conditional_advertisement/r1/bgpd.conf
Normal 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
|
||||||
|
!
|
19
tests/topotests/bgp_conditional_advertisement/r1/zebra.conf
Normal file
19
tests/topotests/bgp_conditional_advertisement/r1/zebra.conf
Normal 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
|
||||||
|
!
|
44
tests/topotests/bgp_conditional_advertisement/r2/bgpd.conf
Normal file
44
tests/topotests/bgp_conditional_advertisement/r2/bgpd.conf
Normal 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
|
||||||
|
!
|
15
tests/topotests/bgp_conditional_advertisement/r2/zebra.conf
Normal file
15
tests/topotests/bgp_conditional_advertisement/r2/zebra.conf
Normal 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
|
||||||
|
!
|
11
tests/topotests/bgp_conditional_advertisement/r3/bgpd.conf
Normal file
11
tests/topotests/bgp_conditional_advertisement/r3/bgpd.conf
Normal 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
|
||||||
|
!
|
||||||
|
|
12
tests/topotests/bgp_conditional_advertisement/r3/zebra.conf
Normal file
12
tests/topotests/bgp_conditional_advertisement/r3/zebra.conf
Normal 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
|
||||||
|
!
|
@ -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))
|
Loading…
Reference in New Issue
Block a user