diff options
| author | Donatas Abraitis <donatas.abraitis@gmail.com> | 2021-01-21 15:03:40 +0200 | 
|---|---|---|
| committer | Donatas Abraitis <donatas.abraitis@gmail.com> | 2021-01-21 16:00:53 +0200 | 
| commit | 2721dd613f5f456920b76fd1ed6de2422dc73c71 (patch) | |
| tree | 6b74acea19c4b5609517169e4fbcf1e390f33b90 | |
| parent | 7dac521ffbcd3744b9f43ca45c862eac67e148cf (diff) | |
bgpd: Set NO_ADVERTISE community if blackhole community received
rfc7999:
A BGP speaker receiving an announcement tagged with the BLACKHOLE
community SHOULD add the NO_ADVERTISE or NO_EXPORT community as
defined in [RFC1997], or a similar community, to prevent propagation
of the prefix outside the local AS.  The community to prevent
propagation SHOULD be chosen according to the operator's routing
policy.
Sent:
```
router bgp 65534
 no bgp ebgp-requires-policy
 neighbor 192.168.0.2 remote-as 65030
 !
 address-family ipv4 unicast
  redistribute connected
  neighbor 192.168.0.2 route-map spine out
 exit-address-family
 !
!
ip prefix-list self seq 5 permit 192.168.100.1/32
!
route-map spine permit 10
 match ip address prefix-list self
 set community blackhole
!
```
Received:
```
spine1-debian-9# show ip bgp 192.168.100.1/32
BGP routing table entry for 192.168.100.1/32
Paths: (1 available, best #1, table default, inform peer to blackhole prefix)
  Not advertised to any peer
  65534
    192.168.0.1 from 192.168.0.1 (192.168.100.1)
      Origin incomplete, metric 0, valid, external, best (First path received)
      Community: blackhole no-advertise
      Last update: Thu Jan 21 12:56:39 2021
```
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
| -rw-r--r-- | bgpd/bgp_community.c | 2 | ||||
| -rw-r--r-- | bgpd/bgp_community.h | 1 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 42 | ||||
| -rw-r--r-- | bgpd/bgp_routemap.c | 5 | 
4 files changed, 49 insertions, 1 deletions
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index f722a8dbc7..43138b82f6 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -56,7 +56,7 @@ void community_free(struct community **com)  }  /* Add one community value to the community. */ -static void community_add_val(struct community *com, uint32_t val) +void community_add_val(struct community *com, uint32_t val)  {  	com->size++;  	if (com->val) diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h index b99f38ab64..2a1fbf526a 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -88,6 +88,7 @@ extern struct community *community_delete(struct community *,  					  struct community *);  extern struct community *community_dup(struct community *);  extern bool community_include(struct community *, uint32_t); +extern void community_add_val(struct community *com, uint32_t val);  extern void community_del_val(struct community *, uint32_t *);  extern unsigned long community_count(void);  extern struct hash *community_hash(void); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c4ab223b7f..a88f39f46b 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3505,6 +3505,34 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,  	return ret;  } +static void bgp_attr_add_no_advertise_community(struct attr *attr) +{ +	struct community *old; +	struct community *new; +	struct community *merge; +	struct community *noadv; + +	old = attr->community; +	noadv = community_str2com("no-advertise"); + +	if (old) { +		merge = community_merge(community_dup(old), noadv); + +		if (!old->refcnt) +			community_free(&old); + +		new = community_uniq_sort(merge); +		community_free(&merge); +	} else { +		new = community_dup(noadv); +	} + +	community_free(&noadv); + +	attr->community = new; +	attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); +} +  int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,  	       struct attr *attr, afi_t afi, safi_t safi, int type,  	       int sub_type, struct prefix_rd *prd, mpls_label_t *label, @@ -3697,6 +3725,20 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,  	if (peer->sort == BGP_PEER_EBGP) { +		/* rfc7999: +		 * A BGP speaker receiving an announcement tagged with the +		 * BLACKHOLE community SHOULD add the NO_ADVERTISE or +		 * NO_EXPORT community as defined in RFC1997, or a +		 * similar community, to prevent propagation of the +		 * prefix outside the local AS. The community to prevent +		 * propagation SHOULD be chosen according to the operator's +		 * routing policy. +		 */ +		if (new_attr.community +		    && community_include(new_attr.community, +					 COMMUNITY_BLACKHOLE)) +			bgp_attr_add_no_advertise_community(&new_attr); +  		/* If we receive the graceful-shutdown community from an eBGP  		 * peer we must lower local-preference */  		if (new_attr.community diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index ceaf8c0963..6bcde16269 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -4822,6 +4822,11 @@ DEFUN (set_community,  			buffer_putstr(b, "no-export");  			continue;  		} +		if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg)) +		    == 0) { +			buffer_putstr(b, "blackhole"); +			continue; +		}  		if (strncmp(argv[i]->arg, "graceful-shutdown",  			    strlen(argv[i]->arg))  		    == 0) {  | 
