]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Set NO_ADVERTISE community if blackhole community received
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Thu, 21 Jan 2021 13:03:40 +0000 (15:03 +0200)
committerDonatas Abraitis <donatas.abraitis@gmail.com>
Thu, 21 Jan 2021 14:00:53 +0000 (16:00 +0200)
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>
bgpd/bgp_community.c
bgpd/bgp_community.h
bgpd/bgp_route.c
bgpd/bgp_routemap.c

index f722a8dbc79d6e15a534c61a72a657be7ade49b3..43138b82f68fe32e8d6b09c55d942ea1805b4274 100644 (file)
@@ -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)
index b99f38ab6465d1c073373f394b97b00c7d74355d..2a1fbf526aaa310c0ad4521ee3043ffcd9fded8d 100644 (file)
@@ -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);
index c4ab223b7f5956b54904638b2170e50e95f99a57..a88f39f46b6118ebcef2f64a9aa9a7980f2e71a5 100644 (file)
@@ -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
index ceaf8c0963255fdb7740b1f1aa7ccfae60573313..6bcde16269e15d4150fd5934701f6bd97f6c13be 100644 (file)
@@ -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) {