summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorMadhuri Kuruganti <k.madhuri@samsung.com>2020-10-05 19:40:56 +0200
committerMadhuri Kuruganti <k.madhuri@samsung.com>2020-10-27 11:45:36 +0100
commitc385f82af3dd9ad84b842b79c5fe83616c2507bd (patch)
tree2a7a6b15546fed890d97058b75a8ef8ebba6e198 /bgpd
parentbgpd: conditional advertisement - with route-map filter (diff)
downloadfrr-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.c409
-rw-r--r--bgpd/bgp_conditional_adv.h95
-rw-r--r--bgpd/bgp_packet.c3
-rw-r--r--bgpd/bgp_route.c23
-rw-r--r--bgpd/bgp_routemap.c2
-rw-r--r--bgpd/bgp_vty.c5
-rw-r--r--bgpd/bgpd.c18
-rw-r--r--bgpd/bgpd.h17
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
};