bgpd: conditional advertisement - other match rules support

Sample Configuration with prefix-list and community match rules
---------------------------------------------------------------

R1 ------- R2(DUT) ------- R3

Router2# show running-config
Building configuration...

Current configuration:
!
frr version 7.6-dev-MyOwnFRRVersion
frr defaults traditional
hostname router
log file /var/log/frr/bgpd.log
log syslog informational
hostname Router2
service integrated-vtysh-config
!
debug bgp updates in
debug bgp updates out
!
debug route-map
!
ip route 20.20.0.0/16 blackhole
ipv6 route 2001:db8::200/128 blackhole
!
interface enp0s9
 ip address 10.10.10.2/24
!
interface enp0s10
 ip address 10.10.20.2/24
!
interface lo
 ip address 2.2.2.2/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 1.1.1.5/32
ip prefix-list DEFAULT seq 10 permit 1.1.1.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 T2 seq 5 permit 1.1.1.5/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 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
!
line vty
!
end
Router2#

Router2# show ip bgp 0.0.0.0
BGP routing table entry for 0.0.0.0/0
Paths: (1 available, best #1, table default)
  Advertised to non peer-group peers:
  10.10.10.1 10.10.20.3
  1
    10.10.10.1 from 10.10.10.1 (10.139.224.1)
      Origin IGP, metric 0, valid, external, best (First path received)
      Community: 64848:3011 65011:200 65013:200
      Last update: Tue Oct  6 02:39:42 2020
Router2#

Sample output with non-exist-map when default route present in table
--------------------------------------------------------------------
Router2# show ip bgp
BGP table version is 4, local router ID is 2.2.2.2, 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
*> 1.1.1.1/32       10.10.10.1               0             0 1 i
*> 1.1.1.5/32       10.10.10.1               0             0 1 i
*> 10.139.224.0/20  10.10.10.1               0             0 1 ?

Displayed  4 routes and 4 total paths

Router2# show ip bgp neighbors 10.10.20.3 advertised-routes
BGP table version is 4, local router ID is 2.2.2.2, 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
*> 1.1.1.5/32       0.0.0.0                                0 1 i   		<<<<<<<<<  non-exist-map : 0.0.0.0/0 is present so, 10.139.224.0/20 not advertised

Total number of prefixes 2

Sample output with non-exist-map when default route not present in table
------------------------------------------------------------------------
Router2# show ip bgp
BGP table version is 5, local router ID is 2.2.2.2, 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
*> 1.1.1.1/32       10.10.10.1               0             0 1 i
*> 1.1.1.5/32       10.10.10.1               0             0 1 i
*> 10.139.224.0/20  10.10.10.1               0             0 1 ?

Displayed  3 routes and 3 total paths
Router2#
Router2#
Router2# show ip bgp neighbors 10.10.20.3 advertised-routes
BGP table version is 5, local router ID is 2.2.2.2, 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
*> 1.1.1.1/32       0.0.0.0                                0 1 i
*> 1.1.1.5/32       0.0.0.0                                0 1 i
*> 10.139.224.0/20  0.0.0.0                                0 1 ?                <<<<<<<<<  non-exist-map : 0.0.0.0/0 is not present so, 10.139.224.0/20 advertised

Total number of prefixes 3
Router2#

Sample output with exist-map when default route present in table
--------------------------------------------------------------------
Router2# show ip bgp
BGP table version is 8, local router ID is 2.2.2.2, 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
*> 1.1.1.1/32       10.10.10.1               0             0 1 i
*> 1.1.1.5/32       10.10.10.1               0             0 1 i
*> 10.139.224.0/20  10.10.10.1               0             0 1 ?

Displayed  4 routes and 4 total paths
Router2#
Router2#
Router2#
Router2#
Router2# show ip bgp neighbors 10.10.20.3 advertised-routes
BGP table version is 8, local router ID is 2.2.2.2, 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
*> 1.1.1.1/32       0.0.0.0                                0 1 i
*> 1.1.1.5/32       0.0.0.0                                0 1 i
*> 10.139.224.0/20  0.0.0.0                                0 1 ?		<<<<<<<<<  exist-map : 0.0.0.0/0 is present so, 10.139.224.0/20 advertised

Total number of prefixes 4
Router2#

Sample output with exist-map when default route not present in table
--------------------------------------------------------------------
Router2# show ip bgp
BGP table version is 9, local router ID is 2.2.2.2, 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
*> 1.1.1.1/32       10.10.10.1               0             0 1 i
*> 1.1.1.5/32       10.10.10.1               0             0 1 i
*> 10.139.224.0/20  10.10.10.1               0             0 1 ?

Displayed  3 routes and 3 total paths
Router2#
Router2#
Router2#
Router2# show ip bgp neighbors 10.10.20.3 advertised-routes
BGP table version is 9, local router ID is 2.2.2.2, 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
*> 1.1.1.5/32       0.0.0.0                                0 1 i		<<<<<<<<<  exist-map : 0.0.0.0/0 is not present so, 10.139.224.0/20 not advertised

Total number of prefixes 1
Router2#

Signed-off-by: Madhuri Kuruganti <k.madhuri@samsung.com>
This commit is contained in:
Madhuri Kuruganti 2020-10-05 23:10:56 +05:30
parent c5aec50b81
commit c385f82af3
8 changed files with 164 additions and 404 deletions

View File

@ -22,197 +22,115 @@
const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
/* We just need bgp_dest node matches with filter prefix. So no need to
* traverse each path here.
*/
struct bgp_dest *bgp_dest_matches_filter_prefix(struct bgp_table *table,
struct filter *filter)
{
uint32_t check_addr;
uint32_t check_mask;
struct in_addr mask;
struct bgp_dest *dest = NULL;
struct bgp_path_info *pi = NULL;
const struct prefix *dest_p = NULL;
struct filter_cisco *cfilter = NULL;
struct filter_zebra *zfilter = NULL;
if (filter->cisco) {
cfilter = &filter->u.cfilter;
for (dest = bgp_table_top(table); dest;
dest = bgp_route_next(dest)) {
dest_p = (struct prefix *)bgp_dest_get_prefix(dest);
if (!dest_p)
continue;
pi = bgp_dest_get_bgp_path_info(dest);
if (!pi)
continue;
check_addr = dest_p->u.prefix4.s_addr
& ~cfilter->addr_mask.s_addr;
if (memcmp(&check_addr, &cfilter->addr.s_addr,
sizeof(check_addr))
!= 0)
continue;
if (cfilter->extended) {
masklen2ip(dest_p->prefixlen, &mask);
check_mask = mask.s_addr
& ~cfilter->mask_mask.s_addr;
if (memcmp(&check_mask, &cfilter->mask.s_addr,
sizeof(check_mask))
!= 0)
continue;
}
return dest;
}
} else {
zfilter = &filter->u.zfilter;
for (dest = bgp_table_top(table); dest;
dest = bgp_route_next(dest)) {
dest_p = bgp_dest_get_prefix(dest);
if (!dest_p)
continue;
pi = bgp_dest_get_bgp_path_info(dest);
if (!pi)
continue;
if ((zfilter->prefix.family != dest_p->family)
|| (zfilter->exact
&& (zfilter->prefix.prefixlen
!= dest_p->prefixlen)))
continue;
else if (!prefix_match(&zfilter->prefix, dest_p))
continue;
else
return dest;
}
}
return NULL;
}
enum route_map_cmd_result_t
static route_map_result_t
bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table *table,
struct route_map *rmap)
{
afi_t afi;
struct access_list *alist = NULL;
struct filter *alist_filter = NULL;
struct bgp_dest *dest = NULL;
struct route_map_rule *match = NULL;
enum route_map_cmd_result_t ret = RMAP_NOOP;
struct bgp_dest *dest;
struct attr dummy_attr;
struct bgp_path_info path;
const struct prefix *dest_p;
struct bgp_path_info *pi;
route_map_result_t ret = RMAP_PERMITMATCH;
if (!is_rmap_valid(rmap))
return ret;
/* If several match commands are configured, all must succeed for a
* given route in order for that route to match the clause (logical AND)
*/
for (match = rmap->head->match_list.head; match; match = match->next) {
if (!match->cmd || !match->cmd->str || !match->value)
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
dest_p = bgp_dest_get_prefix(dest);
if (!dest_p)
continue;
ret = RMAP_NOMATCH;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
dummy_attr = *pi->attr;
path.peer = pi->peer;
path.attr = &dummy_attr;
afi = get_afi_from_match_rule(match->cmd->str);
if (afi == AFI_MAX)
return ret;
alist = access_list_lookup(afi, (char *)match->value);
if (!alist)
return ret;
/* If a match command refers to several objects in one
* command either of them should match (i.e logical OR)
*/
FOREACH_ACCESS_LIST_FILTER(alist, alist_filter) {
dest = bgp_dest_matches_filter_prefix(table,
alist_filter);
if (!dest)
continue;
ret = RMAP_MATCH;
break;
ret = route_map_apply(rmap, dest_p, RMAP_BGP, &path);
if (ret == RMAP_PERMITMATCH)
return ret;
}
/* None of the access-list's filter prefix of this Match rule is
* not matched with BGP table.
* So we do not need to process the remaining match rules
*/
if (ret != RMAP_MATCH)
break;
}
/* route-map prefix not matched with prefixes in BGP table */
return ret;
}
bool bgp_conditional_adv_routes(struct peer *peer, afi_t afi, safi_t safi,
struct bgp_table *table, struct route_map *rmap,
bool advertise)
static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
safi_t safi, struct bgp_table *table,
struct route_map *rmap,
enum advertise advertise)
{
int addpath_capable;
afi_t match_afi;
bool ret = false;
bool route_advertised = false;
const struct prefix *dest_p;
struct attr dummy_attr, attr;
struct bgp_path_info path;
struct bgp_path_info *pi;
struct peer_af *paf = NULL;
struct bgp_dest *dest = NULL;
struct access_list *alist = NULL;
struct filter *alist_filter = NULL;
struct route_map_rule *match = NULL;
struct update_subgroup *subgrp = NULL;
paf = peer_af_find(peer, afi, safi);
if (!paf)
return ret;
return;
subgrp = PAF_SUBGRP(paf);
/* Ignore if subgroup doesn't exist (implies AF is not negotiated) */
if (!subgrp)
return ret;
if (!is_rmap_valid(rmap))
return ret;
return;
addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
/* If several match commands are configured, all must succeed for a
* given route in order for that route to match the clause (i.e. logical
* AND). But we are skipping this rule and advertising if match rule is
* valid and access-lists are having valid prefix - To be discussed
*/
for (match = rmap->head->match_list.head; match; match = match->next) {
if (!match->cmd || !match->cmd->str || !match->value)
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
dest_p = bgp_dest_get_prefix(dest);
if (!dest_p)
continue;
match_afi = get_afi_from_match_rule(match->cmd->str);
if (match_afi == AFI_MAX)
continue;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
dummy_attr = *pi->attr;
path.peer = pi->peer;
path.attr = &dummy_attr;
alist = access_list_lookup(match_afi, (char *)match->value);
if (!alist)
continue;
if (safi == SAFI_LABELED_UNICAST)
safi = SAFI_UNICAST;
/* If a match command refers to several objects in one
* command either of them should match (i.e logical OR)
*/
FOREACH_ACCESS_LIST_FILTER(alist, alist_filter) {
dest = bgp_dest_matches_filter_prefix(table,
alist_filter);
if (!dest)
if (route_map_apply(rmap, dest_p, RMAP_BGP, &path)
!= RMAP_PERMITMATCH)
continue;
ret = advertise_dest_routes(subgrp, dest, peer, afi,
safi, addpath_capable,
advertise);
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
|| (addpath_capable
&& bgp_addpath_tx_path(
peer->addpath_type[afi][safi],
pi))) {
/* Atleast one route advertised */
if (!route_advertised && ret)
route_advertised = true;
/* 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 ((advertise == 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));
}
}
}
}
return route_advertised;
}
/* Handler of conditional advertisement timer event.
@ -230,9 +148,7 @@ static int bgp_conditional_adv_timer(struct thread *t)
struct bgp_filter *filter = NULL;
struct listnode *node, *nnode = NULL;
struct update_subgroup *subgrp = NULL;
enum route_map_cmd_result_t ret, prev_ret;
bool route_advertised = false;
int adv_conditional = 0;
route_map_result_t ret;
bgp = THREAD_ARG(t);
assert(bgp);
@ -243,138 +159,67 @@ static int bgp_conditional_adv_timer(struct thread *t)
/* 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)
* does exist(exist-map)/not exist(non-exist-map) in BGP table
* based on condition(exist-map or non-exist map)
*/
FOREACH_AFI_SAFI (afi, safi) {
if (strmatch(get_afi_safi_str(afi, safi, true), "Unknown"))
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
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;
/* Process conditional advertisement for each peer */
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
FOREACH_AFI_SAFI (afi, safi) {
if (strmatch(get_afi_safi_str(afi, safi, true),
"Unknown"))
continue;
if (!peer->afc[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))
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;
/* cmap (route-map attached to exist-map or
* non-exist-map) map validation
*/
adv_conditional = 0;
ret = bgp_check_rmap_prefixes_in_bgp_table(table,
filter->advmap.cmap);
prev_ret =
peer->advmap_info[afi][safi].cmap_prev_status;
switch (ret) {
case RMAP_NOOP:
if (prev_ret == RMAP_NOOP) {
peer->advmap_info[afi][safi]
.config_change = false;
continue;
}
peer->advmap_info[afi][safi].cmap_prev_status =
ret;
break;
case RMAP_MATCH:
/* Handle configuration changes */
if (peer->advmap_info[afi][safi]
.config_change) {
adv_conditional =
(filter->advmap.condition
== CONDITION_EXIST)
? NLRI
: WITHDRAW;
} else {
if (prev_ret != RMAP_MATCH)
adv_conditional =
(filter->advmap
.condition
== CONDITION_EXIST)
? NLRI
: WITHDRAW;
}
peer->advmap_info[afi][safi].cmap_prev_status =
ret;
break;
case RMAP_NOMATCH:
/* Handle configuration changes */
if (peer->advmap_info[afi][safi]
.config_change) {
adv_conditional =
(filter->advmap.condition
== CONDITION_EXIST)
? WITHDRAW
: NLRI;
} else {
if (prev_ret != RMAP_NOMATCH)
adv_conditional =
(filter->advmap
.condition
== CONDITION_EXIST)
? WITHDRAW
: NLRI;
}
peer->advmap_info[afi][safi].cmap_prev_status =
ret;
break;
case RMAP_OKAY:
case RMAP_ERROR:
default:
break;
}
/* amap (route-map attached to advertise-map)
* validation.
*/
ret = is_rmap_valid(filter->advmap.amap) ? RMAP_MATCH
: RMAP_NOOP;
if ((ret == RMAP_NOOP) && (prev_ret == RMAP_NOOP))
continue;
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 (adv_conditional == NLRI)
filter->advmap.status = true;
else if (adv_conditional == WITHDRAW)
filter->advmap.status = false;
else {
/* no change in advertise status. So, only
* previously withdrawn routes will be
* advertised if needed.
*/
}
if (filter->advmap.condition == CONDITION_EXIST)
filter->advmap.advertise =
(ret == RMAP_PERMITMATCH) ? ADVERTISE
: WITHDRAW;
else
filter->advmap.advertise =
(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_info[afi][safi].config_change) {
if (peer->advmap_config_change[afi][safi]) {
paf = peer_af_find(peer, afi, safi);
if (paf) {
update_subgroup_split_peer(paf, NULL);
@ -383,27 +228,15 @@ static int bgp_conditional_adv_timer(struct thread *t)
subgroup_announce_table(
paf->subgroup, NULL);
}
peer->advmap_info[afi][safi].config_change =
false;
peer->advmap_config_change[afi][safi] = false;
}
/* Send update as per the conditional advertisement */
if (adv_conditional) {
route_advertised = bgp_conditional_adv_routes(
peer, afi, safi, table,
filter->advmap.amap,
filter->advmap.status);
/* amap_prev_status is only to check whether we
* have announced any routes(advertise/withdraw)
* or not. filter->advmap.status will have the
* actual filter status
*/
peer->advmap_info[afi][safi].amap_prev_status =
route_advertised ? RMAP_MATCH
: RMAP_NOOP;
}
bgp_conditional_adv_routes(peer, afi, safi, table,
filter->advmap.amap,
filter->advmap.advertise);
}
peer->advmap_table_change = false;
}
return 0;
}
@ -418,9 +251,7 @@ void bgp_conditional_adv_enable(struct peer *peer, afi_t afi, safi_t safi)
* and advertise/withdraw routes only when there is a change in BGP
* table w.r.t conditional routes
*/
peer->advmap_info[afi][safi].amap_prev_status = RMAP_NOOP;
peer->advmap_info[afi][safi].cmap_prev_status = RMAP_NOOP;
peer->advmap_info[afi][safi].config_change = true;
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.

View File

@ -36,105 +36,10 @@ extern "C" {
/* Polling time for monitoring condition-map routes in route table */
#define CONDITIONAL_ROUTES_POLL_TIME 60
#define FOREACH_ACCESS_LIST_FILTER(alist, filter) \
for (filter = alist->head; filter; filter = filter->next)
static inline bool is_rmap_valid(struct route_map *rmap)
{
if (!rmap || !rmap->head)
return false;
/* Doesn't make sense to configure advertise
* or condition map in deny/any clause.
*/
if (rmap->head->type != RMAP_PERMIT)
return false;
/* If a match command is not present, all routes match the clause */
if (!rmap->head->match_list.head)
return false;
return true;
}
static inline afi_t get_afi_from_match_rule(const char *str)
{
if (!strcmp(str, "ip address"))
return AFI_IP;
else if (!strcmp(str, "ipv6 address"))
return AFI_IP6;
else
return AFI_MAX;
}
static inline bool advertise_dest_routes(struct update_subgroup *subgrp,
struct bgp_dest *dest,
struct peer *peer, afi_t afi,
safi_t safi, int addpath_capable,
bool advertise)
{
struct attr attr;
struct bgp_path_info *pi = NULL;
const struct prefix *dest_p = NULL;
bool route_advertised = false;
dest_p = (struct prefix *)bgp_dest_get_prefix(dest);
if (!dest_p)
return route_advertised;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
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 (advertise
&& subgroup_announce_check(dest, pi, subgrp, dest_p,
&attr, true)) {
bgp_adj_out_set_subgroup(dest, subgrp, &attr,
pi);
route_advertised = true;
} 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));
route_advertised = true;
}
}
}
return route_advertised;
}
struct bgp_dest *bgp_dest_matches_filter_prefix(struct bgp_table *table,
struct filter *filter);
extern enum route_map_cmd_result_t
bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table *table,
struct route_map *rmap);
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);
extern bool bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
safi_t safi, struct bgp_table *table,
struct route_map *rmap, bool advertise);
#ifdef __cplusplus
}
#endif

View File

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

View File

@ -2030,6 +2030,27 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
peer->host, p);
bgp_attr_flush(attr);
/* TBD : Not sure if this is the correct way to fetch
* peer from group.
* Notify BGP Conditional advertisement scanner process.
*/
if (ADVERTISE_MAP_NAME(filter)
|| CONDITION_MAP_NAME(filter)) {
struct peer *temp_peer;
struct listnode *temp_node, *temp_nnode = NULL;
for (ALL_LIST_ELEMENTS(bgp->peer, temp_node,
temp_nnode, temp_peer)) {
if (!CHECK_FLAG(peer->flags,
PEER_FLAG_CONFIG_NODE))
continue;
if (strcmp(peer->host, temp_peer->host)
!= 0)
continue;
temp_peer->advmap_table_change = true;
break;
}
}
return false;
}
}
@ -4363,7 +4384,7 @@ static int bgp_announce_route_timer_expired(struct thread *t)
peer_af_announce_route(paf, 1);
/* Notify BGP conditional advertisement scanner percess */
peer->advmap_info[paf->afi][paf->safi].config_change = true;
peer->advmap_config_change[paf->afi][paf->safi] = true;
return 0;
}

View File

@ -3710,7 +3710,7 @@ static void bgp_route_map_process_peer(const char *rmap_name,
peer->default_rmap[afi][safi].map = map;
/* Notify BGP conditional advertisement scanner percess */
peer->advmap_info[afi][safi].config_change = true;
peer->advmap_config_change[afi][safi] = true;
}
static void bgp_route_map_update_peer_group(const char *rmap_name,

View File

@ -11417,8 +11417,9 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
filter->advmap.cname,
filter->advmap.amap ? "*" : "",
filter->advmap.aname,
filter->advmap.status ? "Advertise"
: "Withdraw");
filter->advmap.advertise == ADVERTISE
? "Advertise"
: "Withdraw");
/* Receive prefix count */
vty_out(vty, " %u accepted prefixes\n",

View File

@ -6623,7 +6623,7 @@ int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
filter->advmap.cmap = condition_map;
filter->advmap.condition = condition;
route_map_counter_increment(advertise_map);
peer->advmap_info[afi][safi].config_change = true;
peer->advmap_config_change[afi][safi] = true;
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@ -6631,11 +6631,11 @@ int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
PEER_FT_ADVERTISE_MAP);
/* Hold peer_on_policy_change() until timer thread is called */
/* To increment condition_filter_count and/or create timer */
/* Hold peer_on_policy_change() until timer thread is called.
* Increment condition_filter_count and/or create timer.
*/
if (!filter_exists) {
filter->advmap.status = true;
filter->advmap.advertise = ADVERTISE;
bgp_conditional_adv_enable(peer, afi, safi);
}
/* Skip peer-group mechanics for regular peers. */
@ -6671,11 +6671,11 @@ int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
filter->advmap.condition = condition;
route_map_counter_increment(advertise_map);
/* Hold peer_on_policy_change() until timer thread is called */
/* increment condition_filter_count, create timer if 1st one */
/* Hold peer_on_policy_change() until timer thread is called.
* Increment condition_filter_count, create timer if 1st one
*/
if (!filter_exists) {
filter->advmap.status = true;
filter->advmap.advertise = ADVERTISE;
bgp_conditional_adv_enable(member, afi, safi);
}
}

View File

@ -683,7 +683,7 @@ struct bgp {
struct work_queue *process_queue;
/* BGP Conditional advertisement */
int condition_filter_count;
uint32_t condition_filter_count;
struct thread *t_condition_check;
QOBJ_FIELDS
@ -764,8 +764,10 @@ struct bgp_nexthop {
#define BGP_GTSM_HOPS_CONNECTED 1
/* Advertise map */
#define CONDITION_NON_EXIST 0
#define CONDITION_EXIST 1
#define CONDITION_NON_EXIST false
#define CONDITION_EXIST true
enum advertise { WITHDRAW, ADVERTISE };
#include "filter.h"
@ -811,7 +813,7 @@ struct bgp_filter {
char *cname;
struct route_map *cmap;
bool status;
enum advertise advertise;
} advmap;
};
@ -1471,11 +1473,8 @@ struct peer {
bool as_path_loop_detection;
/* Conditional advertisement */
struct {
bool config_change;
enum route_map_cmd_result_t amap_prev_status;
enum route_map_cmd_result_t cmap_prev_status;
} advmap_info[AFI_MAX][SAFI_MAX];
bool advmap_config_change[AFI_MAX][SAFI_MAX];
bool advmap_table_change;
QOBJ_FIELDS
};