mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-24 02:39:58 +00:00

To avoid USE: ``` ==587645==ERROR: AddressSanitizer: heap-use-after-free on address 0x604000074050 at pc 0x55b34337d96c bp 0x7ffda59bb4c0 sp 0x7ffda59bb4b0 READ of size 8 at 0x604000074050 thread T0 0 0x55b34337d96b in bgp_attr_flush bgpd/bgp_attr.c:1289 1 0x55b34368ef85 in bgp_conditional_adv_routes bgpd/bgp_conditional_adv.c:111 2 0x55b34368ff58 in bgp_conditional_adv_timer bgpd/bgp_conditional_adv.c:301 3 0x7f7d41cdf81c in event_call lib/event.c:1980 4 0x7f7d41c1da37 in frr_run lib/libfrr.c:1214 5 0x55b343371e22 in main bgpd/bgp_main.c:510 6 0x7f7d41517082 in __libc_start_main ../csu/libc-start.c:308 7 0x55b3433769fd in _start (/usr/lib/frr/bgpd+0x2e29fd) 0x604000074050 is located 0 bytes inside of 40-byte region [0x604000074050,0x604000074078) freed by thread T0 here: #0 0x7f7d4207540f in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:122 1 0x55b343396afd in community_free bgpd/bgp_community.c:41 2 0x55b343396afd in community_free bgpd/bgp_community.c:28 3 0x55b343397373 in community_intern bgpd/bgp_community.c:458 4 0x55b34337bed4 in bgp_attr_intern bgpd/bgp_attr.c:967 5 0x55b34368165b in bgp_advertise_attr_intern bgpd/bgp_advertise.c:106 6 0x55b3435277d7 in bgp_adj_out_set_subgroup bgpd/bgp_updgrp_adv.c:587 7 0x55b34368f36b in bgp_conditional_adv_routes bgpd/bgp_conditional_adv.c:125 8 0x55b34368ff58 in bgp_conditional_adv_timer bgpd/bgp_conditional_adv.c:301 9 0x7f7d41cdf81c in event_call lib/event.c:1980 10 0x7f7d41c1da37 in frr_run lib/libfrr.c:1214 11 0x55b343371e22 in main bgpd/bgp_main.c:510 12 0x7f7d41517082 in __libc_start_main ../csu/libc-start.c:308 previously allocated by thread T0 here: #0 0x7f7d42075a06 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:153 1 0x7f7d41c3c28e in qcalloc lib/memory.c:105 2 0x55b3433976e8 in community_dup bgpd/bgp_community.c:514 3 0x55b34350273a in route_set_community bgpd/bgp_routemap.c:2589 4 0x7f7d41c96c06 in route_map_apply_ext lib/routemap.c:2690 5 0x55b34368f2d8 in bgp_conditional_adv_routes bgpd/bgp_conditional_adv.c:107 6 0x55b34368ff58 in bgp_conditional_adv_timer bgpd/bgp_conditional_adv.c:301 7 0x7f7d41cdf81c in event_call lib/event.c:1980 8 0x7f7d41c1da37 in frr_run lib/libfrr.c:1214 9 0x55b343371e22 in main bgpd/bgp_main.c:510 10 0x7f7d41517082 in __libc_start_main ../csu/libc-start.c:308 ``` And also a crash: ``` (gdb) bt 0 raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 1 0x00007ff3b7048ce0 in core_handler (signo=6, siginfo=0x7ffc8cf724b0, context=<optimized out>) at lib/sigevent.c:246 2 <signal handler called> 3 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 4 0x00007ff3b6bb8859 in __GI_abort () at abort.c:79 5 0x00007ff3b6c2326e in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ff3b6d4d298 "%s\n") at ../sysdeps/posix/libc_fatal.c:155 6 0x00007ff3b6c2b2fc in malloc_printerr ( str=str@entry=0x7ff3b6d4f628 "double free or corruption (fasttop)") at malloc.c:5347 7 0x00007ff3b6c2cc65 in _int_free (av=0x7ff3b6d82b80 <main_arena>, p=0x555c8fa70a10, have_lock=0) at malloc.c:4266 8 0x0000555c8da94bd3 in community_free (com=0x7ffc8cf72e70) at bgpd/bgp_community.c:41 9 community_free (com=com@entry=0x7ffc8cf72e70) at bgpd/bgp_community.c:28 10 0x0000555c8da8afc1 in bgp_attr_flush (attr=attr@entry=0x7ffc8cf73040) at bgpd/bgp_attr.c:1290 11 0x0000555c8dbc0760 in bgp_conditional_adv_routes (peer=peer@entry=0x555c8fa627c0, afi=afi@entry=AFI_IP, safi=SAFI_UNICAST, table=table@entry=0x555c8fa510b0, rmap=0x555c8fa71cb0, update_type=UPDATE_TYPE_ADVERTISE) at bgpd/bgp_conditional_adv.c:111 12 0x0000555c8dbc0b75 in bgp_conditional_adv_timer (t=<optimized out>) at bgpd/bgp_conditional_adv.c:301 13 0x00007ff3b705b84c in event_call (thread=thread@entry=0x7ffc8cf73440) at lib/event.c:1980 14 0x00007ff3b700bf98 in frr_run (master=0x555c8f27c090) at lib/libfrr.c:1214 15 0x0000555c8da85f05 in main (argc=<optimized out>, argv=0x7ffc8cf736a8) at bgpd/bgp_main.c:510 ``` Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
519 lines
15 KiB
C
519 lines
15 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* BGP Conditional advertisement
|
|
* Copyright (C) 2020 Samsung R&D Institute India - Bangalore.
|
|
* Madhurilatha Kuruganti
|
|
*/
|
|
|
|
#include <zebra.h>
|
|
|
|
#include "bgpd/bgp_conditional_adv.h"
|
|
#include "bgpd/bgp_vty.h"
|
|
|
|
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, &path);
|
|
bgp_attr_flush(&dummy_attr);
|
|
|
|
if (ret == RMAP_PERMITMATCH) {
|
|
bgp_dest_unlock_node(dest);
|
|
bgp_cond_adv_debug(
|
|
"%s: Condition map routes present in BGP table",
|
|
__func__);
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
bgp_cond_adv_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)
|
|
{
|
|
bool 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 advmap_attr = {0}, attr = {0};
|
|
struct bgp_path_info_extra path_extra = {0};
|
|
route_map_result_t ret;
|
|
|
|
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;
|
|
|
|
subgrp->pscount = 0;
|
|
SET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING);
|
|
|
|
bgp_cond_adv_debug("%s: %s routes to/from %s for %s", __func__,
|
|
update_type == UPDATE_TYPE_ADVERTISE ? "Advertise"
|
|
: "Withdraw",
|
|
peer->host, get_afi_safi_str(afi, safi, false));
|
|
|
|
addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
|
|
|
|
SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
|
|
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) {
|
|
advmap_attr = *pi->attr;
|
|
|
|
/* Fill temp path_info */
|
|
prep_for_rmap_apply(&path, &path_extra, dest, pi,
|
|
pi->peer, &advmap_attr);
|
|
|
|
RESET_FLAG(advmap_attr.rmap_change_flags);
|
|
|
|
ret = route_map_apply(rmap, dest_p, &path);
|
|
if (ret != RMAP_PERMITMATCH ||
|
|
!bgp_check_selected(pi, peer, addpath_capable, afi,
|
|
safi)) {
|
|
bgp_attr_flush(&advmap_attr);
|
|
continue;
|
|
}
|
|
|
|
/* 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 == UPDATE_TYPE_ADVERTISE &&
|
|
subgroup_announce_check(dest, pi, subgrp, dest_p,
|
|
&attr, &advmap_attr)) {
|
|
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));
|
|
|
|
bgp_attr_flush(&advmap_attr);
|
|
}
|
|
}
|
|
}
|
|
UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING);
|
|
}
|
|
|
|
/* Handler of conditional advertisement timer event.
|
|
* Each route in the condition-map is evaluated.
|
|
*/
|
|
static void bgp_conditional_adv_timer(struct event *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;
|
|
bool advmap_table_changed = false;
|
|
|
|
bgp = EVENT_ARG(t);
|
|
assert(bgp);
|
|
|
|
event_add_timer(bm->master, bgp_conditional_adv_timer, bgp,
|
|
bgp->condition_check_period, &bgp->t_condition_check);
|
|
|
|
/* loop through each peer and check if we have peers with
|
|
* advmap_table_change attribute set, to make sure we send
|
|
* conditional advertisements properly below.
|
|
* peer->advmap_table_change is added on incoming BGP UPDATES,
|
|
* but here it's used for outgoing UPDATES, hence we need to
|
|
* check if at least one peer got advmap_table_change.
|
|
*/
|
|
for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
|
|
if (peer->advmap_table_change) {
|
|
advmap_table_changed = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* 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_established(peer->connection))
|
|
continue;
|
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
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] &&
|
|
!advmap_table_changed)
|
|
continue;
|
|
|
|
if (BGP_DEBUG(cond_adv, COND_ADV)) {
|
|
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)
|
|
? UPDATE_TYPE_ADVERTISE
|
|
: UPDATE_TYPE_WITHDRAW;
|
|
else
|
|
filter->advmap.update_type =
|
|
(ret == RMAP_PERMITMATCH)
|
|
? UPDATE_TYPE_WITHDRAW
|
|
: UPDATE_TYPE_ADVERTISE;
|
|
|
|
/*
|
|
* Update condadv update type so
|
|
* subgroup_announce_check() can properly apply
|
|
* outbound policy according to advertisement state
|
|
*/
|
|
paf = peer_af_find(peer, afi, safi);
|
|
if (paf && (SUBGRP_PEER(PAF_SUBGRP(paf))
|
|
->filter[afi][safi]
|
|
.advmap.update_type !=
|
|
filter->advmap.update_type)) {
|
|
/* Handle change to peer advmap */
|
|
bgp_cond_adv_debug(
|
|
"%s: advmap.update_type changed for peer %s, adjusting update_group.",
|
|
__func__, peer->host);
|
|
|
|
update_group_adjust_peer(paf);
|
|
}
|
|
|
|
/* 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]) {
|
|
|
|
bgp_cond_adv_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));
|
|
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;
|
|
}
|
|
}
|
|
|
|
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 at least one of its
|
|
* neighbors (AFI/SAFI). So just increment the counter.
|
|
*/
|
|
if (++bgp->condition_filter_count > 1) {
|
|
bgp_cond_adv_debug("%s: condition_filter_count %d", __func__,
|
|
bgp->condition_filter_count);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Register for conditional routes polling timer */
|
|
if (!event_is_scheduled(bgp->t_condition_check))
|
|
event_add_timer(bm->master, bgp_conditional_adv_timer, bgp, 0,
|
|
&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) {
|
|
bgp_cond_adv_debug("%s: condition_filter_count %d", __func__,
|
|
bgp->condition_filter_count);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Last filter removed. So cancel conditional routes polling thread. */
|
|
EVENT_OFF(bgp->t_condition_check);
|
|
}
|
|
|
|
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->advmap, 0, sizeof(filter->advmap));
|
|
|
|
/* 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);
|
|
|
|
/* Process peer route updates. */
|
|
peer_on_policy_change(peer, afi, safi, 1);
|
|
|
|
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 = UPDATE_TYPE_ADVERTISE;
|
|
bgp_conditional_adv_enable(peer, afi, safi);
|
|
}
|
|
|
|
/* Process peer route updates. */
|
|
peer_on_policy_change(peer, afi, safi, 1);
|
|
}
|
|
|
|
/* Set advertise-map to the peer. */
|
|
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
|
|
* explicitly 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. */
|
|
bgp_cond_adv_debug("%s: Send normal update to %s for %s",
|
|
__func__, peer->host,
|
|
get_afi_safi_str(afi, safi, false));
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Remove configuration on all peer-group members, unless they are
|
|
* explicitly 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. */
|
|
bgp_cond_adv_debug("%s: Send normal update to %s for %s ",
|
|
__func__, member->host,
|
|
get_afi_safi_str(afi, safi, false));
|
|
}
|
|
|
|
return 0;
|
|
}
|