Skip to content

Commit

Permalink
bgpd: conditional advertisement
Browse files Browse the repository at this point in the history
Implemented as per the feature description given in the source link.

Descriprion:
The BGP conditional advertisement feature uses the non-exist-map or exist-map
and the advertise-map keywords of the neighbor advertise-map command in order
to track routes by the route prefix.

non-exist-map :
If a route prefix is not present in output of the non-exist-map command, then
the route specified by the advertise-map command is announced.

exist-map :
If a route prefix is present in output of the exist-map command, then the route
specified by the advertise-map command is announced.

The conditional BGP announcements are sent in addition to the normal
announcements that a BGP router sends to its peers.

The conditional advertisement process is triggered by the BGP scanner process,
which runs every 60 seconds. This means that the maximum time for the conditional
advertisement to take effect is 60 seconds. The conditional advertisement can take
effect sooner, depending on when the tracked route is removed from the BGP table
and when the next instance of the BGP scanner occurs.

Sample Configuration on DUT
---------------------------
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 130.130.0.0/16 blackhole
!
interface enp0s9
 ip address 10.10.10.2/24
!
interface enp0s10
 ip address 10.10.20.2/24
!
interface lo
 ip address 128.16.16.1/24
!
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
  network 128.16.16.0/24
  network 130.130.0.0/16
  neighbor 10.10.10.1 soft-reconfiguration inbound
  neighbor 10.10.10.1 advertise-map ADVERTISE non-exist-map CONDITION
  neighbor 10.10.20.3 soft-reconfiguration inbound
 exit-address-family
!
access-list 60 seq 5 permit 128.16.16.0/24 exact-match
access-list 65 seq 5 permit 192.168.50.0/24 exact-match
access-list CONDITION seq 5 permit 192.168.50.0/24
access-list ADVERTISE seq 5 permit 128.16.16.0/24
!
route-map ADVERTISE permit 10
 match ip address ADVERTISE
!
route-map CONDITION permit 10
 match ip address CONDITION
!
line vty
!
end
Router2#

Sample output
-------------
Router2# show ip bgp neighbors 10.10.10.1
BGP neighbor is 10.10.10.1, remote AS 1, local AS 2, external link

!--- Output suppressed.

 For address family: IPv4 Unicast
  Update group 1, subgroup 1
  Packet Queue length 0
  Inbound soft reconfiguration allowed
  Community attribute sent to this neighbor(all)
  Condition NON_EXIST, Condition-map *CONDITION, Advertise-map *ADVERTISE, status: Withdraw
  1 accepted prefixes

  Connections established 1; dropped 0
  Last reset 00:21:05,  Waiting for peer OPEN

!--- Output suppressed.

Router2#

Router2# show ip bgp
BGP table version is 6, local router ID is 128.16.16.1, 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
*> 128.16.16.0/24   0.0.0.0                  0         32768 i
*> 130.130.0.0/16   0.0.0.0                  0         32768 i
*> 192.168.50.0/24  10.10.20.3               0             0 3 i
*> 200.200.200.0/24 10.10.10.1               0             0 1 i

Displayed  4 routes and 4 total paths
Router2#

Here 128.16.16.0/24(prefix in advertise-map) is withdrawn by conditional
advertisement scanner as the prefix(192.168.50.0/24) specified by
non-exist-map is present in BGP table.

Router2# show ip bgp neighbors 10.10.10.1 advertised-routes
BGP table version is 6, local router ID is 128.16.16.1, 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
*> 130.130.0.0/16   0.0.0.0                  0         32768 i
*> 192.168.50.0/24  0.0.0.0                                0 3 i
*> 200.200.200.0/24 0.0.0.0                                0 1 i

Total number of prefixes 3
Router2#

After Removing 192.168.50.0/24(prefix present in non-exist-map), prefix present in
advertise-map(128.16.16.0/24) is advertised

Router2# show ip bgp
BGP table version is 7, local router ID is 128.16.16.1, 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
*> 128.16.16.0/24   0.0.0.0                  0         32768 i
*> 130.130.0.0/16   0.0.0.0                  0         32768 i
*> 200.200.200.0/24 10.10.10.1               0             0 1 i

Displayed  3 routes and 3 total paths
Router2#
Router2#
Router2# show ip bgp neighbors 10.10.10.1 advertised-routes
BGP table version is 7, local router ID is 128.16.16.1, 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
*> 128.16.16.0/24   0.0.0.0                  0         32768 i
*> 130.130.0.0/16   0.0.0.0                  0         32768 i
*> 200.200.200.0/24 0.0.0.0                                0 1 i

Total number of prefixes 3
Router2#
Router2#
Router2#

Signed-off-by: Madhuri Kuruganti <k.madhuri@samsung.com>
  • Loading branch information
Madhuri Kuruganti committed Sep 27, 2020
1 parent e4d09f6 commit 021212d
Show file tree
Hide file tree
Showing 9 changed files with 1,076 additions and 1 deletion.
494 changes: 494 additions & 0 deletions bgpd/bgp_conditional_adv.c

Large diffs are not rendered by default.

130 changes: 130 additions & 0 deletions bgpd/bgp_conditional_adv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* BGP Conditional advertisement
* Copyright (C) 2020 Samsung Research Institute Bangalore.
* Madhurilatha Kuruganti
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef _FRR_BGP_CONDITION_ADV_H
#define _FRR_BGP_CONDITION_ADV_H
#include <zebra.h>
#include "prefix.h"
#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_updgrp.h"

#ifdef __cplusplus
extern "C" {
#endif

/* 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_str(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))) {
if (advertise
&& subgroup_announce_check(dest, pi, subgrp, dest_p,
&attr)) {
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 int bgp_conditional_adv_enable(struct peer *, afi_t, safi_t);
extern int bgp_conditional_adv_disable(struct peer *, afi_t, safi_t);
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

#endif /* _FRR_BGP_CONDITION_ADV_H */
8 changes: 8 additions & 0 deletions bgpd/bgp_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,14 @@ struct bgp_aggregate {
#define UNSUPPRESS_MAP_NAME(F) ((F)->usmap.name)
#define UNSUPPRESS_MAP(F) ((F)->usmap.map)

#define ADVERTISE_MAP_NAME(F) ((F)->advmap.aname)
#define ADVERTISE_MAP(F) ((F)->advmap.amap)

#define ADVERTISE_CONDITION(F) ((F)->advmap.condition)

#define CONDITION_MAP_NAME(F) ((F)->advmap.cname)
#define CONDITION_MAP(F) ((F)->advmap.cmap)

/* path PREFIX (addpath rxid NUMBER) */
#define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32

Expand Down
12 changes: 12 additions & 0 deletions bgpd/bgp_routemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -3695,6 +3695,18 @@ static void bgp_route_map_process_peer(const char *rmap_name,
if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
filter->usmap.map = map;

if (filter->advmap.aname
&& (strcmp(rmap_name, filter->advmap.aname) == 0)) {
filter->advmap.amap = map;
peer->advmap_info[afi][safi].config_change = true;
}

if (filter->advmap.cname
&& (strcmp(rmap_name, filter->advmap.cname) == 0)) {
filter->advmap.cmap = map;
peer->advmap_info[afi][safi].config_change = true;
}

if (peer->default_rmap[afi][safi].name
&& (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
peer->default_rmap[afi][safi].map = map;
Expand Down
28 changes: 28 additions & 0 deletions bgpd/bgp_updgrp.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,19 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
MTYPE_BGP_FILTER_NAME, UNSUPPRESS_MAP_NAME(srcfilter));
UNSUPPRESS_MAP(dstfilter) = UNSUPPRESS_MAP(srcfilter);
}

if (ADVERTISE_MAP_NAME(srcfilter)) {
ADVERTISE_MAP_NAME(dstfilter) = XSTRDUP(
MTYPE_BGP_FILTER_NAME, ADVERTISE_MAP_NAME(srcfilter));
ADVERTISE_MAP(dstfilter) = ADVERTISE_MAP(srcfilter);
ADVERTISE_CONDITION(dstfilter) = ADVERTISE_CONDITION(srcfilter);
}

if (CONDITION_MAP_NAME(srcfilter)) {
CONDITION_MAP_NAME(dstfilter) = XSTRDUP(
MTYPE_BGP_FILTER_NAME, CONDITION_MAP_NAME(srcfilter));
CONDITION_MAP(dstfilter) = CONDITION_MAP(srcfilter);
}
}

/**
Expand All @@ -218,6 +231,10 @@ static void conf_release(struct peer *src, afi_t afi, safi_t safi)

XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name);

XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->advmap.aname);

XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->advmap.cname);

XFREE(MTYPE_BGP_PEER_HOST, src->host);
}

Expand Down Expand Up @@ -353,6 +370,11 @@ static unsigned int updgrp_hash_key_make(const void *p)
strlen(filter->usmap.name), SEED1),
key);

if (filter->advmap.aname)
key = jhash_1word(jhash(filter->advmap.aname,
strlen(filter->advmap.aname), SEED1),
key);

if (peer->default_rmap[afi][safi].name)
key = jhash_1word(
jhash(peer->default_rmap[afi][safi].name,
Expand Down Expand Up @@ -481,6 +503,12 @@ static bool updgrp_hash_cmp(const void *p1, const void *p2)
&& strcmp(fl1->usmap.name, fl2->usmap.name)))
return false;

if ((fl1->advmap.aname && !fl2->advmap.aname)
|| (!fl1->advmap.aname && fl2->advmap.aname)
|| (fl1->advmap.aname && fl2->advmap.aname
&& strcmp(fl1->advmap.aname, fl2->advmap.aname)))
return false;

if ((pe1->default_rmap[afi][safi].name
&& !pe2->default_rmap[afi][safi].name)
|| (!pe1->default_rmap[afi][safi].name
Expand Down
Loading

0 comments on commit 021212d

Please sign in to comment.