]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: conditional advertisement - other match rules support
authorMadhuri Kuruganti <k.madhuri@samsung.com>
Mon, 5 Oct 2020 17:40:56 +0000 (23:10 +0530)
committerMadhuri Kuruganti <k.madhuri@samsung.com>
Tue, 27 Oct 2020 10:45:36 +0000 (16:15 +0530)
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>
bgpd/bgp_conditional_adv.c
bgpd/bgp_conditional_adv.h
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_routemap.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index f601e7a795084d6fd6818d18b505e10e18934b73..999326d9c3434e1edf781c42b18c04d07c6b99a2 100644 (file)
 
 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.
index cd857958a22fe00bc690e842cb9ac730d9463252..5dcd3607d940773239d3b29ff1553fb137a110da 100644 (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
index d75d032c5cb63351a38b2a073e34101a36b4bf6d..a23acda0a85ce654ef1f13062d22e9e5a93652ad 100644 (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;
 }
 
index 48f38dfec7f1a0e4e466549d1d3d90b4078c495e..1b611ebe7b52b67e0ad624565f497d294f507469 100644 (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;
 }
index 2abebbcbc3b024b4b7d3332165f0bd3dcb9789e0..e4a9c29000675b40e5c6ec8c9f7c50f1728cf72e 100644 (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,
index 480e3172af554f9a90fc59cd81da1190f35556a3..5bfda7d5707f600994fed454d76b4c0407a8a4a2 100644 (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",
index 7fbad67e938e14cb2ad2663b6dccea27f7de045d..194049f017ce4fe2cff0e74744103afa80beb4bf 100644 (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);
                }
        }
index 293583460f3fcadde69cdcac5d67b60af102f697..05fe2330b4ac795e4f484b2ab3127b8ff22e74e4 100644 (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
 };