diff options
author | Madhuri Kuruganti <k.madhuri@samsung.com> | 2020-10-05 19:40:56 +0200 |
---|---|---|
committer | Madhuri Kuruganti <k.madhuri@samsung.com> | 2020-10-27 11:45:36 +0100 |
commit | c385f82af3dd9ad84b842b79c5fe83616c2507bd (patch) | |
tree | 2a7a6b15546fed890d97058b75a8ef8ebba6e198 /bgpd | |
parent | bgpd: conditional advertisement - with route-map filter (diff) | |
download | frr-c385f82af3dd9ad84b842b79c5fe83616c2507bd.tar.xz frr-c385f82af3dd9ad84b842b79c5fe83616c2507bd.zip |
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>
Diffstat (limited to 'bgpd')
-rw-r--r-- | bgpd/bgp_conditional_adv.c | 409 | ||||
-rw-r--r-- | bgpd/bgp_conditional_adv.h | 95 | ||||
-rw-r--r-- | bgpd/bgp_packet.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 23 | ||||
-rw-r--r-- | bgpd/bgp_routemap.c | 2 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 5 | ||||
-rw-r--r-- | bgpd/bgpd.c | 18 | ||||
-rw-r--r-- | bgpd/bgpd.h | 17 |
8 files changed, 166 insertions, 406 deletions
diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c index f601e7a79..999326d9c 100644 --- a/bgpd/bgp_conditional_adv.c +++ b/bgpd/bgp_conditional_adv.c @@ -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; - - 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) + 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; + + 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; - - 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; + 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; - /* 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; - - alist = access_list_lookup(match_afi, (char *)match->value); - if (!alist) - continue; - - if (safi == SAFI_LABELED_UNICAST) - safi = SAFI_UNICAST; + 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; - /* 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); - - /* Atleast one route advertised */ - if (!route_advertised && ret) - route_advertised = true; + 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 == 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. diff --git a/bgpd/bgp_conditional_adv.h b/bgpd/bgp_conditional_adv.h index cd857958a..5dcd3607d 100644 --- a/bgpd/bgp_conditional_adv.h +++ b/bgpd/bgp_conditional_adv.h @@ -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 diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index d75d032c5..a23acda0a 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -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; } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 48f38dfec..1b611ebe7 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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; } diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 2abebbcbc..e4a9c2900 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -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, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 480e3172a..5bfda7d57 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -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", diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 7fbad67e9..194049f01 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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); } } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 293583460..05fe2330b 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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 }; |