mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-04 06:32:57 +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();
|
||||
|
||||
/* Notify BGP Conditional advertisement scanner process */
|
||||
peer->advmap_table_change = true;
|
||||
|
||||
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)
|
||||
{
|
||||
if (family == AF_INET) {
|
||||
@ -1674,7 +1701,8 @@ static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
|
||||
|
||||
bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
|
||||
struct update_subgroup *subgrp,
|
||||
const struct prefix *p, struct attr *attr)
|
||||
const struct prefix *p, struct attr *attr,
|
||||
bool skip_rmap_check)
|
||||
{
|
||||
struct bgp_filter *filter;
|
||||
struct peer *from;
|
||||
@ -1989,7 +2017,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
|
||||
bgp_peer_as_override(bgp, afi, safi, peer, attr);
|
||||
|
||||
/* Route map & unsuppress-map apply. */
|
||||
if (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi)) {
|
||||
if (!skip_rmap_check
|
||||
&& (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
|
||||
struct bgp_path_info rmap_path = {0};
|
||||
struct bgp_path_info_extra dummy_rmap_path_extra = {0};
|
||||
struct attr dummy_attr = {0};
|
||||
@ -2487,7 +2516,8 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
|
||||
/* Announcement to the subgroup. If the route is filtered withdraw it.
|
||||
*/
|
||||
if (selected) {
|
||||
if (subgroup_announce_check(dest, selected, subgrp, p, &attr))
|
||||
if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
|
||||
false))
|
||||
bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
|
||||
else
|
||||
bgp_adj_out_unset_subgroup(dest, subgrp, 1,
|
||||
@ -4360,6 +4390,10 @@ static int bgp_announce_route_timer_expired(struct thread *t)
|
||||
return 0;
|
||||
|
||||
peer_af_announce_route(paf, 1);
|
||||
|
||||
/* Notify BGP conditional advertisement scanner percess */
|
||||
peer->advmap_config_change[paf->afi][paf->safi] = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -454,6 +454,14 @@ struct bgp_aggregate {
|
||||
#define UNSUPPRESS_MAP_NAME(F) ((F)->usmap.name)
|
||||
#define UNSUPPRESS_MAP(F) ((F)->usmap.map)
|
||||
|
||||
#define ADVERTISE_MAP_NAME(F) ((F)->advmap.aname)
|
||||
#define ADVERTISE_MAP(F) ((F)->advmap.amap)
|
||||
|
||||
#define ADVERTISE_CONDITION(F) ((F)->advmap.condition)
|
||||
|
||||
#define CONDITION_MAP_NAME(F) ((F)->advmap.cname)
|
||||
#define CONDITION_MAP(F) ((F)->advmap.cmap)
|
||||
|
||||
/* path PREFIX (addpath rxid NUMBER) */
|
||||
#define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32
|
||||
|
||||
@ -663,6 +671,8 @@ extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
|
||||
struct bgp_path_info *path, int display,
|
||||
json_object *json);
|
||||
|
||||
extern void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp);
|
||||
|
||||
extern void subgroup_process_announce_selected(struct update_subgroup *subgrp,
|
||||
struct bgp_path_info *selected,
|
||||
struct bgp_dest *dest,
|
||||
@ -671,7 +681,8 @@ extern void subgroup_process_announce_selected(struct update_subgroup *subgrp,
|
||||
extern bool subgroup_announce_check(struct bgp_dest *dest,
|
||||
struct bgp_path_info *pi,
|
||||
struct update_subgroup *subgrp,
|
||||
const struct prefix *p, struct attr *attr);
|
||||
const struct prefix *p, struct attr *attr,
|
||||
bool skip_rmap_check);
|
||||
|
||||
extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer);
|
||||
extern void bgp_process_queues_drain_immediate(void);
|
||||
|
@ -3695,9 +3695,22 @@ static void bgp_route_map_process_peer(const char *rmap_name,
|
||||
if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
|
||||
filter->usmap.map = map;
|
||||
|
||||
if (filter->advmap.aname
|
||||
&& (strcmp(rmap_name, filter->advmap.aname) == 0)) {
|
||||
filter->advmap.amap = map;
|
||||
}
|
||||
|
||||
if (filter->advmap.cname
|
||||
&& (strcmp(rmap_name, filter->advmap.cname) == 0)) {
|
||||
filter->advmap.cmap = map;
|
||||
}
|
||||
|
||||
if (peer->default_rmap[afi][safi].name
|
||||
&& (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
|
||||
peer->default_rmap[afi][safi].map = map;
|
||||
|
||||
/* Notify BGP conditional advertisement scanner percess */
|
||||
peer->advmap_config_change[afi][safi] = true;
|
||||
}
|
||||
|
||||
static void bgp_route_map_update_peer_group(const char *rmap_name,
|
||||
|
@ -195,6 +195,19 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
|
||||
MTYPE_BGP_FILTER_NAME, UNSUPPRESS_MAP_NAME(srcfilter));
|
||||
UNSUPPRESS_MAP(dstfilter) = UNSUPPRESS_MAP(srcfilter);
|
||||
}
|
||||
|
||||
if (ADVERTISE_MAP_NAME(srcfilter)) {
|
||||
ADVERTISE_MAP_NAME(dstfilter) = XSTRDUP(
|
||||
MTYPE_BGP_FILTER_NAME, ADVERTISE_MAP_NAME(srcfilter));
|
||||
ADVERTISE_MAP(dstfilter) = ADVERTISE_MAP(srcfilter);
|
||||
ADVERTISE_CONDITION(dstfilter) = ADVERTISE_CONDITION(srcfilter);
|
||||
}
|
||||
|
||||
if (CONDITION_MAP_NAME(srcfilter)) {
|
||||
CONDITION_MAP_NAME(dstfilter) = XSTRDUP(
|
||||
MTYPE_BGP_FILTER_NAME, CONDITION_MAP_NAME(srcfilter));
|
||||
CONDITION_MAP(dstfilter) = CONDITION_MAP(srcfilter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -218,6 +231,10 @@ static void conf_release(struct peer *src, afi_t afi, safi_t safi)
|
||||
|
||||
XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name);
|
||||
|
||||
XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->advmap.aname);
|
||||
|
||||
XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->advmap.cname);
|
||||
|
||||
XFREE(MTYPE_BGP_PEER_HOST, src->host);
|
||||
}
|
||||
|
||||
@ -353,6 +370,11 @@ static unsigned int updgrp_hash_key_make(const void *p)
|
||||
strlen(filter->usmap.name), SEED1),
|
||||
key);
|
||||
|
||||
if (filter->advmap.aname)
|
||||
key = jhash_1word(jhash(filter->advmap.aname,
|
||||
strlen(filter->advmap.aname), SEED1),
|
||||
key);
|
||||
|
||||
if (peer->default_rmap[afi][safi].name)
|
||||
key = jhash_1word(
|
||||
jhash(peer->default_rmap[afi][safi].name,
|
||||
@ -481,6 +503,12 @@ static bool updgrp_hash_cmp(const void *p1, const void *p2)
|
||||
&& strcmp(fl1->usmap.name, fl2->usmap.name)))
|
||||
return false;
|
||||
|
||||
if ((fl1->advmap.aname && !fl2->advmap.aname)
|
||||
|| (!fl1->advmap.aname && fl2->advmap.aname)
|
||||
|| (fl1->advmap.aname && fl2->advmap.aname
|
||||
&& strcmp(fl1->advmap.aname, fl2->advmap.aname)))
|
||||
return false;
|
||||
|
||||
if ((pe1->default_rmap[afi][safi].name
|
||||
&& !pe2->default_rmap[afi][safi].name)
|
||||
|| (!pe1->default_rmap[afi][safi].name
|
||||
|
@ -215,6 +215,9 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify BGP Conditional advertisement */
|
||||
bgp_notify_conditional_adv_scanner(subgrp);
|
||||
}
|
||||
|
||||
return UPDWALK_CONTINUE;
|
||||
@ -642,7 +645,8 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
|
||||
peer->addpath_type[afi][safi],
|
||||
ri))) {
|
||||
if (subgroup_announce_check(dest, ri, subgrp,
|
||||
dest_p, &attr))
|
||||
dest_p, &attr,
|
||||
false))
|
||||
bgp_adj_out_set_subgroup(dest, subgrp,
|
||||
&attr, ri);
|
||||
else {
|
||||
@ -827,7 +831,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
|
||||
if (subgroup_announce_check(
|
||||
dest, pi, subgrp,
|
||||
bgp_dest_get_prefix(dest),
|
||||
&attr))
|
||||
&attr, false))
|
||||
bgp_adj_out_set_subgroup(
|
||||
dest, subgrp, &attr,
|
||||
pi);
|
||||
|
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 outgoing routes\n")
|
||||
|
||||
/* Set advertise-map to the peer. */
|
||||
static int peer_advertise_map_set_vty(struct vty *vty, const char *ip_str,
|
||||
afi_t afi, safi_t safi,
|
||||
const char *advertise_str,
|
||||
const char *condition_str, bool condition,
|
||||
bool set)
|
||||
{
|
||||
int ret = CMD_WARNING_CONFIG_FAILED;
|
||||
struct peer *peer;
|
||||
struct route_map *advertise_map;
|
||||
struct route_map *condition_map;
|
||||
|
||||
peer = peer_and_group_lookup_vty(vty, ip_str);
|
||||
if (!peer)
|
||||
return ret;
|
||||
|
||||
condition_map = route_map_lookup_warn_noexist(vty, condition_str);
|
||||
advertise_map = route_map_lookup_warn_noexist(vty, advertise_str);
|
||||
|
||||
if (set)
|
||||
ret = peer_advertise_map_set(peer, afi, safi, advertise_str,
|
||||
advertise_map, condition_str,
|
||||
condition_map, condition);
|
||||
else
|
||||
ret = peer_advertise_map_unset(peer, afi, safi, advertise_str,
|
||||
advertise_map, condition_str,
|
||||
condition_map, condition);
|
||||
|
||||
return bgp_vty_return(vty, ret);
|
||||
}
|
||||
|
||||
DEFPY (neighbor_advertise_map,
|
||||
neighbor_advertise_map_cmd,
|
||||
"[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map WORD$advertise_str <exist-map|non-exist-map>$exist WORD$condition_str",
|
||||
NO_STR
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR2
|
||||
"Route-map to conditionally advertise routes\n"
|
||||
"Name of advertise map\n"
|
||||
"Advertise routes only if prefixes in exist-map are installed in BGP table\n"
|
||||
"Advertise routes only if prefixes in non-exist-map are not installed in BGP table\n"
|
||||
"Name of the exist or non exist map\n")
|
||||
{
|
||||
bool condition = CONDITION_EXIST;
|
||||
|
||||
if (!strcmp(exist, "non-exist-map"))
|
||||
condition = CONDITION_NON_EXIST;
|
||||
|
||||
return peer_advertise_map_set_vty(vty, neighbor, bgp_node_afi(vty),
|
||||
bgp_node_safi(vty), advertise_str,
|
||||
condition_str, condition, !no);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(neighbor_advertise_map, neighbor_advertise_map_hidden_cmd,
|
||||
"[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map WORD$advertise_str <exist-map|non-exist-map>$exist WORD$condition_str",
|
||||
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
|
||||
"Route-map to conditionally advertise routes\n"
|
||||
"Name of advertise map\n"
|
||||
"Advertise routes only if prefixes in exist-map are installed in BGP table\n"
|
||||
"Advertise routes only if prefixes in non-exist-map are not installed in BGP table\n"
|
||||
"Name of the exist or non exist map\n")
|
||||
|
||||
/* Set route-map to the peer. */
|
||||
static int peer_route_map_set_vty(struct vty *vty, const char *ip_str,
|
||||
afi_t afi, safi_t safi, const char *name_str,
|
||||
@ -10879,6 +10941,7 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
|
||||
json_object *json_prefA = NULL;
|
||||
json_object *json_prefB = NULL;
|
||||
json_object *json_addr = NULL;
|
||||
json_object *json_advmap = NULL;
|
||||
|
||||
if (use_json) {
|
||||
json_addr = json_object_new_object();
|
||||
@ -11153,6 +11216,26 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
|
||||
"selectiveUnsuppressRouteMap",
|
||||
filter->usmap.name);
|
||||
|
||||
/* advertise-map */
|
||||
if (filter->advmap.aname) {
|
||||
json_advmap = json_object_new_object();
|
||||
json_object_string_add(json_advmap, "condition",
|
||||
filter->advmap.condition
|
||||
? "EXIST"
|
||||
: "NON_EXIST");
|
||||
json_object_string_add(json_advmap, "conditionMap",
|
||||
filter->advmap.cname);
|
||||
json_object_string_add(json_advmap, "advertiseMap",
|
||||
filter->advmap.aname);
|
||||
json_object_string_add(json_advmap, "advertiseStatus",
|
||||
filter->advmap.update_type
|
||||
== ADVERTISE
|
||||
? "Advertise"
|
||||
: "Withdraw");
|
||||
json_object_object_add(json_addr, "advertiseMap",
|
||||
json_advmap);
|
||||
}
|
||||
|
||||
/* Receive prefix count */
|
||||
json_object_int_add(json_addr, "acceptedPrefixCounter",
|
||||
p->pcount[afi][safi]);
|
||||
@ -11448,6 +11531,20 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
|
||||
filter->usmap.map ? "*" : "",
|
||||
filter->usmap.name);
|
||||
|
||||
/* advertise-map */
|
||||
if (filter->advmap.aname && filter->advmap.cname)
|
||||
vty_out(vty,
|
||||
" Condition %s, Condition-map %s%s, Advertise-map %s%s, status: %s\n",
|
||||
filter->advmap.condition ? "EXIST"
|
||||
: "NON_EXIST",
|
||||
filter->advmap.cmap ? "*" : "",
|
||||
filter->advmap.cname,
|
||||
filter->advmap.amap ? "*" : "",
|
||||
filter->advmap.aname,
|
||||
filter->advmap.update_type == ADVERTISE
|
||||
? "Advertise"
|
||||
: "Withdraw");
|
||||
|
||||
/* Receive prefix count */
|
||||
vty_out(vty, " %u accepted prefixes\n",
|
||||
p->pcount[afi][safi]);
|
||||
@ -15112,6 +15209,10 @@ static bool peergroup_filter_check(struct peer *peer, afi_t afi, safi_t safi,
|
||||
return !!(filter->map[direct].name);
|
||||
case PEER_FT_UNSUPPRESS_MAP:
|
||||
return !!(filter->usmap.name);
|
||||
case PEER_FT_ADVERTISE_MAP:
|
||||
return !!(filter->advmap.aname
|
||||
&& ((filter->advmap.condition == direct)
|
||||
&& filter->advmap.cname));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -15297,6 +15398,18 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
||||
vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
|
||||
filter->usmap.name);
|
||||
|
||||
/* advertise-map : always applied in OUT direction*/
|
||||
if (peergroup_filter_check(peer, afi, safi, PEER_FT_ADVERTISE_MAP,
|
||||
CONDITION_NON_EXIST))
|
||||
vty_out(vty,
|
||||
" neighbor %s advertise-map %s non-exist-map %s\n",
|
||||
addr, filter->advmap.aname, filter->advmap.cname);
|
||||
|
||||
if (peergroup_filter_check(peer, afi, safi, PEER_FT_ADVERTISE_MAP,
|
||||
CONDITION_EXIST))
|
||||
vty_out(vty, " neighbor %s advertise-map %s exist-map %s\n",
|
||||
addr, filter->advmap.aname, filter->advmap.cname);
|
||||
|
||||
/* filter-list. */
|
||||
if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
|
||||
FILTER_IN))
|
||||
@ -17501,6 +17614,17 @@ void bgp_vty_init(void)
|
||||
install_element(BGP_VPNV6_NODE, &neighbor_unsuppress_map_cmd);
|
||||
install_element(BGP_VPNV6_NODE, &no_neighbor_unsuppress_map_cmd);
|
||||
|
||||
/* "neighbor advertise-map" commands. */
|
||||
install_element(BGP_NODE, &neighbor_advertise_map_hidden_cmd);
|
||||
install_element(BGP_IPV4_NODE, &neighbor_advertise_map_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &neighbor_advertise_map_cmd);
|
||||
install_element(BGP_IPV4L_NODE, &neighbor_advertise_map_cmd);
|
||||
install_element(BGP_IPV6_NODE, &neighbor_advertise_map_cmd);
|
||||
install_element(BGP_IPV6M_NODE, &neighbor_advertise_map_cmd);
|
||||
install_element(BGP_IPV6L_NODE, &neighbor_advertise_map_cmd);
|
||||
install_element(BGP_VPNV4_NODE, &neighbor_advertise_map_cmd);
|
||||
install_element(BGP_VPNV6_NODE, &neighbor_advertise_map_cmd);
|
||||
|
||||
/* neighbor maximum-prefix-out commands. */
|
||||
install_element(BGP_NODE, &neighbor_maximum_prefix_out_cmd);
|
||||
install_element(BGP_NODE, &no_neighbor_maximum_prefix_out_cmd);
|
||||
|
167
bgpd/bgpd.c
167
bgpd/bgpd.c
@ -54,6 +54,7 @@
|
||||
#include "bgpd/bgp_debug.h"
|
||||
#include "bgpd/bgp_errors.h"
|
||||
#include "bgpd/bgp_community.h"
|
||||
#include "bgpd/bgp_conditional_adv.h"
|
||||
#include "bgpd/bgp_attr.h"
|
||||
#include "bgpd/bgp_regex.h"
|
||||
#include "bgpd/bgp_clist.h"
|
||||
@ -6585,6 +6586,172 @@ int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void peer_advertise_map_filter_update(struct peer *peer, afi_t afi,
|
||||
safi_t safi, const char *amap_name,
|
||||
struct route_map *amap,
|
||||
const char *cmap_name,
|
||||
struct route_map *cmap,
|
||||
bool condition, bool set)
|
||||
{
|
||||
struct bgp_filter *filter;
|
||||
bool filter_exists = false;
|
||||
|
||||
filter = &peer->filter[afi][safi];
|
||||
|
||||
/* advertise-map is already configured. */
|
||||
if (filter->advmap.aname) {
|
||||
filter_exists = true;
|
||||
XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.aname);
|
||||
XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.cname);
|
||||
}
|
||||
|
||||
route_map_counter_decrement(filter->advmap.amap);
|
||||
|
||||
/* Removed advertise-map configuration */
|
||||
if (!set) {
|
||||
memset(filter, 0, sizeof(struct bgp_filter));
|
||||
|
||||
/* decrement condition_filter_count delete timer if
|
||||
* this is the last advertise-map to be removed.
|
||||
*/
|
||||
if (filter_exists)
|
||||
bgp_conditional_adv_disable(peer, afi, safi);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update filter data with newly configured values. */
|
||||
filter->advmap.aname = XSTRDUP(MTYPE_BGP_FILTER_NAME, amap_name);
|
||||
filter->advmap.cname = XSTRDUP(MTYPE_BGP_FILTER_NAME, cmap_name);
|
||||
filter->advmap.amap = amap;
|
||||
filter->advmap.cmap = cmap;
|
||||
filter->advmap.condition = condition;
|
||||
route_map_counter_increment(filter->advmap.amap);
|
||||
peer->advmap_config_change[afi][safi] = true;
|
||||
|
||||
/* Increment condition_filter_count and/or create timer. */
|
||||
if (!filter_exists) {
|
||||
filter->advmap.update_type = ADVERTISE;
|
||||
bgp_conditional_adv_enable(peer, afi, safi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set advertise-map to the peer but do not process peer route updates here. *
|
||||
* Hold filter changes until the conditional routes polling thread is called *
|
||||
* AS we need to advertise/withdraw prefixes (in advertise-map) based on the *
|
||||
* condition (exist-map/non-exist-map) and routes(specified in condition-map) *
|
||||
* in BGP table. So do not call peer_on_policy_change() here, only create *
|
||||
* polling timer thread, update filters and increment condition_filter_count.
|
||||
*/
|
||||
int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
const char *advertise_name,
|
||||
struct route_map *advertise_map,
|
||||
const char *condition_name,
|
||||
struct route_map *condition_map, bool condition)
|
||||
{
|
||||
struct peer *member;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
/* Set configuration on peer. */
|
||||
peer_advertise_map_filter_update(peer, afi, safi, advertise_name,
|
||||
advertise_map, condition_name,
|
||||
condition_map, condition, true);
|
||||
|
||||
/* Check if handling a regular peer & Skip peer-group mechanics. */
|
||||
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
|
||||
/* Set override-flag and process peer route updates. */
|
||||
SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
|
||||
PEER_FT_ADVERTISE_MAP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set configuration on all peer-group members, unless they are
|
||||
* explicitely overriding peer-group configuration.
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
|
||||
/* Skip peers with overridden configuration. */
|
||||
if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
|
||||
PEER_FT_ADVERTISE_MAP))
|
||||
continue;
|
||||
|
||||
/* Set configuration on peer-group member. */
|
||||
peer_advertise_map_filter_update(
|
||||
member, afi, safi, advertise_name, advertise_map,
|
||||
condition_name, condition_map, condition, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unset advertise-map from the peer. */
|
||||
int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
|
||||
const char *advertise_name,
|
||||
struct route_map *advertise_map,
|
||||
const char *condition_name,
|
||||
struct route_map *condition_map, bool condition)
|
||||
{
|
||||
struct peer *member;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
/* advertise-map is not configured */
|
||||
if (!peer->filter[afi][safi].advmap.aname)
|
||||
return 0;
|
||||
|
||||
/* Unset override-flag unconditionally. */
|
||||
UNSET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
|
||||
PEER_FT_ADVERTISE_MAP);
|
||||
|
||||
/* Inherit configuration from peer-group if peer is member. */
|
||||
if (peer_group_active(peer)) {
|
||||
PEER_STR_ATTR_INHERIT(peer, peer->group,
|
||||
filter[afi][safi].advmap.aname,
|
||||
MTYPE_BGP_FILTER_NAME);
|
||||
PEER_ATTR_INHERIT(peer, peer->group,
|
||||
filter[afi][safi].advmap.amap);
|
||||
} else
|
||||
peer_advertise_map_filter_update(
|
||||
peer, afi, safi, advertise_name, advertise_map,
|
||||
condition_name, condition_map, condition, false);
|
||||
|
||||
/* Check if handling a regular peer and skip peer-group mechanics. */
|
||||
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
|
||||
/* Process peer route updates. */
|
||||
if (BGP_DEBUG(update, UPDATE_OUT))
|
||||
zlog_debug("%s: Send normal update to %s for %s",
|
||||
__func__, peer->host,
|
||||
get_afi_safi_str(afi, safi, false));
|
||||
|
||||
peer_on_policy_change(peer, afi, safi, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove configuration on all peer-group members, unless they are
|
||||
* explicitely overriding peer-group configuration.
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
|
||||
/* Skip peers with overridden configuration. */
|
||||
if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
|
||||
PEER_FT_ADVERTISE_MAP))
|
||||
continue;
|
||||
/* Remove configuration on peer-group member. */
|
||||
peer_advertise_map_filter_update(
|
||||
member, afi, safi, advertise_name, advertise_map,
|
||||
condition_name, condition_map, condition, false);
|
||||
|
||||
/* Process peer route updates. */
|
||||
if (BGP_DEBUG(update, UPDATE_OUT))
|
||||
zlog_debug("%s: Send normal update to %s for %s ",
|
||||
__func__, member->host,
|
||||
get_afi_safi_str(afi, safi, false));
|
||||
|
||||
peer_on_policy_change(member, afi, safi, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
uint32_t max, uint8_t threshold, int warning,
|
||||
uint16_t restart, bool force)
|
||||
|
42
bgpd/bgpd.h
42
bgpd/bgpd.h
@ -682,6 +682,10 @@ struct bgp {
|
||||
/* Process Queue for handling routes */
|
||||
struct work_queue *process_queue;
|
||||
|
||||
/* BGP Conditional advertisement */
|
||||
uint32_t condition_filter_count;
|
||||
struct thread *t_condition_check;
|
||||
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
DECLARE_QOBJ_TYPE(bgp)
|
||||
@ -759,6 +763,12 @@ struct bgp_nexthop {
|
||||
#define BGP_GTSM_HOPS_DISABLED 0
|
||||
#define BGP_GTSM_HOPS_CONNECTED 1
|
||||
|
||||
/* Advertise map */
|
||||
#define CONDITION_NON_EXIST false
|
||||
#define CONDITION_EXIST true
|
||||
|
||||
enum update_type { WITHDRAW, ADVERTISE };
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
/* BGP filter structure. */
|
||||
@ -792,6 +802,19 @@ struct bgp_filter {
|
||||
char *name;
|
||||
struct route_map *map;
|
||||
} usmap;
|
||||
|
||||
/* Advertise-map */
|
||||
struct {
|
||||
char *aname;
|
||||
struct route_map *amap;
|
||||
|
||||
bool condition;
|
||||
|
||||
char *cname;
|
||||
struct route_map *cmap;
|
||||
|
||||
enum update_type update_type;
|
||||
} advmap;
|
||||
};
|
||||
|
||||
/* IBGP/EBGP identifier. We also have a CONFED peer, which is to say,
|
||||
@ -1355,6 +1378,7 @@ struct peer {
|
||||
#define PEER_FT_PREFIX_LIST (1U << 2) /* prefix-list */
|
||||
#define PEER_FT_ROUTE_MAP (1U << 3) /* route-map */
|
||||
#define PEER_FT_UNSUPPRESS_MAP (1U << 4) /* unsuppress-map */
|
||||
#define PEER_FT_ADVERTISE_MAP (1U << 5) /* advertise-map */
|
||||
|
||||
/* ORF Prefix-list */
|
||||
struct prefix_list *orf_plist[AFI_MAX][SAFI_MAX];
|
||||
@ -1448,6 +1472,10 @@ struct peer {
|
||||
/* Sender side AS path loop detection. */
|
||||
bool as_path_loop_detection;
|
||||
|
||||
/* Conditional advertisement */
|
||||
bool advmap_config_change[AFI_MAX][SAFI_MAX];
|
||||
bool advmap_table_change;
|
||||
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
DECLARE_QOBJ_TYPE(peer)
|
||||
@ -1939,11 +1967,25 @@ extern int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
const char *name,
|
||||
struct route_map *route_map);
|
||||
|
||||
extern int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
const char *advertise_name,
|
||||
struct route_map *advertise_map,
|
||||
const char *condition_name,
|
||||
struct route_map *condition_map,
|
||||
bool condition);
|
||||
|
||||
extern int peer_password_set(struct peer *, const char *);
|
||||
extern int peer_password_unset(struct peer *);
|
||||
|
||||
extern int peer_unsuppress_map_unset(struct peer *, afi_t, safi_t);
|
||||
|
||||
extern int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
|
||||
const char *advertise_name,
|
||||
struct route_map *advertise_map,
|
||||
const char *condition_name,
|
||||
struct route_map *condition_map,
|
||||
bool condition);
|
||||
|
||||
extern int peer_maximum_prefix_set(struct peer *, afi_t, safi_t, uint32_t,
|
||||
uint8_t, int, uint16_t, bool force);
|
||||
extern int peer_maximum_prefix_unset(struct peer *, afi_t, safi_t);
|
||||
|
@ -61,6 +61,7 @@ bgpd_libbgp_a_SOURCES = \
|
||||
bgpd/bgp_bfd.c \
|
||||
bgpd/bgp_clist.c \
|
||||
bgpd/bgp_community.c \
|
||||
bgpd/bgp_conditional_adv.c \
|
||||
bgpd/bgp_damp.c \
|
||||
bgpd/bgp_debug.c \
|
||||
bgpd/bgp_dump.c \
|
||||
@ -137,6 +138,7 @@ noinst_HEADERS += \
|
||||
bgpd/bgp_bfd.h \
|
||||
bgpd/bgp_clist.h \
|
||||
bgpd/bgp_community.h \
|
||||
bgpd/bgp_conditional_adv.h \
|
||||
bgpd/bgp_damp.h \
|
||||
bgpd/bgp_debug.h \
|
||||
bgpd/bgp_dump.h \
|
||||
|
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
|
||||
instances.
|
||||
|
||||
.. _bgp-conditional-advertisement:
|
||||
|
||||
BGP Conditional Advertisement
|
||||
-----------------------------
|
||||
The BGP conditional advertisement feature uses the ``non-exist-map`` or the
|
||||
``exist-map`` and the ``advertise-map`` keywords of the neighbor advertise-map
|
||||
command in order to track routes by the route prefix.
|
||||
|
||||
``non-exist-map``
|
||||
1. If a route prefix is not present in the output of non-exist-map command,
|
||||
then advertise the route specified by the advertise-map command.
|
||||
|
||||
2. If a route prefix is present in the output of non-exist-map command,
|
||||
then do not advertise the route specified by the addvertise-map command.
|
||||
|
||||
``exist-map``
|
||||
1. If a route prefix is present in the output of exist-map command,
|
||||
then advertise the route specified by the advertise-map command.
|
||||
|
||||
2. If a route prefix is not present in the output of exist-map command,
|
||||
then do not advertise the route specified by the advertise-map command.
|
||||
|
||||
This feature is useful when some prefixes are advertised to one of its peers
|
||||
only if the information from the other peer is not present (due to failure in
|
||||
peering session or partial reachability etc).
|
||||
|
||||
The conditional BGP announcements are sent in addition to the normal
|
||||
announcements that a BGP router sends to its peer.
|
||||
|
||||
The conditional advertisement process is triggered by the BGP scanner process,
|
||||
which runs every 60 seconds. This means that the maximum time for the conditional
|
||||
advertisement to take effect is 60 seconds. The conditional advertisement can take
|
||||
effect depending on when the tracked route is removed from the BGP table and
|
||||
when the next instance of the BGP scanner occurs.
|
||||
|
||||
.. index:: [no] neighbor A.B.C.D advertise-map NAME [exist-map|non-exist-map] NAME
|
||||
.. clicmd:: [no] neighbor A.B.C.D advertise-map NAME [exist-map|non-exist-map] NAME
|
||||
|
||||
This command enables BGP scanner process to monitor routes specified by
|
||||
exist-map or non-exist-map command in BGP table and conditionally advertises
|
||||
the routes specified by advertise-map command.
|
||||
|
||||
Sample Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
.. code-block:: frr
|
||||
|
||||
interface enp0s9
|
||||
ip address 10.10.10.2/24
|
||||
!
|
||||
interface enp0s10
|
||||
ip address 10.10.20.2/24
|
||||
!
|
||||
interface lo
|
||||
ip address 203.0.113.1/32
|
||||
!
|
||||
router bgp 2
|
||||
bgp log-neighbor-changes
|
||||
no bgp ebgp-requires-policy
|
||||
neighbor 10.10.10.1 remote-as 1
|
||||
neighbor 10.10.20.3 remote-as 3
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
neighbor 10.10.10.1 soft-reconfiguration inbound
|
||||
neighbor 10.10.20.3 soft-reconfiguration inbound
|
||||
neighbor 10.10.20.3 advertise-map ADV-MAP non-exist-map EXIST-MAP
|
||||
exit-address-family
|
||||
!
|
||||
ip prefix-list DEFAULT seq 5 permit 192.0.2.5/32
|
||||
ip prefix-list DEFAULT seq 10 permit 192.0.2.1/32
|
||||
ip prefix-list EXIST seq 5 permit 10.10.10.10/32
|
||||
ip prefix-list DEFAULT-ROUTE seq 5 permit 0.0.0.0/0
|
||||
ip prefix-list IP1 seq 5 permit 10.139.224.0/20
|
||||
!
|
||||
bgp community-list standard DC-ROUTES seq 5 permit 64952:3008
|
||||
bgp community-list standard DC-ROUTES seq 10 permit 64671:501
|
||||
bgp community-list standard DC-ROUTES seq 15 permit 64950:3009
|
||||
bgp community-list standard DEFAULT-ROUTE seq 5 permit 65013:200
|
||||
!
|
||||
route-map ADV-MAP permit 10
|
||||
match ip address prefix-list IP1
|
||||
!
|
||||
route-map ADV-MAP permit 20
|
||||
match community DC-ROUTES
|
||||
!
|
||||
route-map EXIST-MAP permit 10
|
||||
match community DEFAULT-ROUTE
|
||||
match ip address prefix-list DEFAULT-ROUTE
|
||||
!
|
||||
|
||||
Sample Output
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
When default route is present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2.1/32 are not advertised to R3.
|
||||
|
||||
.. code-block:: frr
|
||||
|
||||
Router2# show ip bgp
|
||||
BGP table version is 20, local router ID is 203.0.113.1, vrf id 0
|
||||
Default local pref 100, local AS 2
|
||||
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
|
||||
i internal, r RIB-failure, S Stale, R Removed
|
||||
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
|
||||
Origin codes: i - IGP, e - EGP, ? - incomplete
|
||||
|
||||
Network Next Hop Metric LocPrf Weight Path
|
||||
*> 0.0.0.0/0 10.10.10.1 0 0 1 i
|
||||
*> 10.139.224.0/20 10.10.10.1 0 0 1 ?
|
||||
*> 192.0.2.1/32 10.10.10.1 0 0 1 i
|
||||
*> 192.0.2.5/32 10.10.10.1 0 0 1 i
|
||||
|
||||
Displayed 4 routes and 4 total paths
|
||||
Router2# show ip bgp neighbors 10.10.20.3
|
||||
|
||||
!--- Output suppressed.
|
||||
|
||||
For address family: IPv4 Unicast
|
||||
Update group 7, subgroup 7
|
||||
Packet Queue length 0
|
||||
Inbound soft reconfiguration allowed
|
||||
Community attribute sent to this neighbor(all)
|
||||
Condition NON_EXIST, Condition-map *EXIST-MAP, Advertise-map *ADV-MAP, status: Withdraw
|
||||
0 accepted prefixes
|
||||
|
||||
!--- Output suppressed.
|
||||
|
||||
Router2# show ip bgp neighbors 10.10.20.3 advertised-routes
|
||||
BGP table version is 20, local router ID is 203.0.113.1, vrf id 0
|
||||
Default local pref 100, local AS 2
|
||||
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
|
||||
i internal, r RIB-failure, S Stale, R Removed
|
||||
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
|
||||
Origin codes: i - IGP, e - EGP, ? - incomplete
|
||||
|
||||
Network Next Hop Metric LocPrf Weight Path
|
||||
*> 0.0.0.0/0 0.0.0.0 0 1 i
|
||||
*> 192.0.2.5/32 0.0.0.0 0 1 i
|
||||
|
||||
Total number of prefixes 2
|
||||
|
||||
When default route is not present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2.1/32 are advertised to R3.
|
||||
|
||||
.. code-block:: frr
|
||||
|
||||
Router2# show ip bgp
|
||||
BGP table version is 21, local router ID is 203.0.113.1, vrf id 0
|
||||
Default local pref 100, local AS 2
|
||||
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
|
||||
i internal, r RIB-failure, S Stale, R Removed
|
||||
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
|
||||
Origin codes: i - IGP, e - EGP, ? - incomplete
|
||||
|
||||
Network Next Hop Metric LocPrf Weight Path
|
||||
*> 10.139.224.0/20 10.10.10.1 0 0 1 ?
|
||||
*> 192.0.2.1/32 10.10.10.1 0 0 1 i
|
||||
*> 192.0.2.5/32 10.10.10.1 0 0 1 i
|
||||
|
||||
Displayed 3 routes and 3 total paths
|
||||
|
||||
Router2# show ip bgp neighbors 10.10.20.3
|
||||
|
||||
!--- Output suppressed.
|
||||
|
||||
For address family: IPv4 Unicast
|
||||
Update group 7, subgroup 7
|
||||
Packet Queue length 0
|
||||
Inbound soft reconfiguration allowed
|
||||
Community attribute sent to this neighbor(all)
|
||||
Condition NON_EXIST, Condition-map *EXIST-MAP, Advertise-map *ADV-MAP, status: Advertise
|
||||
0 accepted prefixes
|
||||
|
||||
!--- Output suppressed.
|
||||
|
||||
Router2# show ip bgp neighbors 10.10.20.3 advertised-routes
|
||||
BGP table version is 21, local router ID is 203.0.113.1, vrf id 0
|
||||
Default local pref 100, local AS 2
|
||||
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
|
||||
i internal, r RIB-failure, S Stale, R Removed
|
||||
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
|
||||
Origin codes: i - IGP, e - EGP, ? - incomplete
|
||||
|
||||
Network Next Hop Metric LocPrf Weight Path
|
||||
*> 10.139.224.0/20 0.0.0.0 0 1 ?
|
||||
*> 192.0.2.1/32 0.0.0.0 0 1 i
|
||||
*> 192.0.2.5/32 0.0.0.0 0 1 i
|
||||
|
||||
Total number of prefixes 3
|
||||
Router2#
|
||||
|
||||
.. _bgp-debugging:
|
||||
|
||||
Debugging
|
||||
|
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