bgpd: 'set comm-list delete' stops as soon as it hits a community-list entry with a deny

'set comm-list delete' stops as soon as it hits a community-list entry with
a deny

Reviewed By: sharpd@cumulusnetworks.com
Testing Done:

'set comm-list FOO delete' stops evaluating the community-list as soon as
we hit
the first "delete" statement. This makes it impossible to use
community-lists
where you deny some subset of communities to delete and then permit all of
the
others.

This patch changes the behavior so that we no longer exit the
community-list at
the first delete statement. Here is our baseline, we are receiving multiple
communities from 10.1.1.2 for the 10.1.3.0/24 prefix.

qct-ly6-04# show ip bgp 10.1.3.0/24
  BGP routing table entry for 10.1.3.0/24
  Paths: (1 available, best #1, table Default-IP-Routing-Table)
  Not advertised to any peer
  Local
  10.1.1.2 (metric 20) from 10.1.1.2 (10.1.1.2)
    Origin IGP, metric 0, localpref 100, valid, internal, best
    Community: 1:1 1:2 1:3 20:1 20:2 20:3 99:1
    Last update: Wed Mar 4 13:50:36 2015

qct-ly6-04#

We apply the following FOO route-map inbound to this peer and soft clear
the peer
!
ip community-list expanded BAD_COMMS permit 99:.*
ip community-list expanded BAD_COMMS deny 1:.*
ip community-list expanded BAD_COMMS permit 20.*
!
route-map FOO permit 10
set comm-list BAD_COMMS delete
!
router bgp 10
neighbor 10.1.1.2 route-map FOO in
!

qct-ly6-04# clear ip bgp * soft in
qct-ly6-04# show ip bgp 10.1.3.0/24
  BGP routing table entry for 10.1.3.0/24
  Paths: (1 available, best #1, table Default-IP-Routing-Table)
  Not advertised to any peer
  Local
  10.1.1.2 (metric 20) from 10.1.1.2 (10.1.1.2)
    Origin IGP, metric 0, localpref 100, valid, internal, best
    Community: 1:1 1:2 1:3
    Last update: Wed Mar 4 13:51:12 2015

qct-ly6-04#
qct-ly6-04#

We deleted all communities flagged as "permit" by the BAD_COMMS
community-list
while leaving the ones matched by "deny 1:.*" alone.

 #endif /* _QUAGGA_BGP_COMMUNITY_H */

'set comm-list delete' stops as soon as it hits a community-list entry with a deny

Ticket: CM-3513
Reviewed By: sharpd@cumulusnetworks.com
Testing Done:

'set comm-list FOO delete' stops evaluating the community-list as soon as we hit
the first "delete" statement. This makes it impossible to use community-lists
where you deny some subset of communities to delete and then permit all of the
others.

This patch changes the behavior so that we no longer exit the community-list at
the first delete statement. Here is our baseline, we are receiving multiple
communities from 10.1.1.2 for the 10.1.3.0/24 prefix.

qct-ly6-04# show ip bgp 10.1.3.0/24
  BGP routing table entry for 10.1.3.0/24
  Paths: (1 available, best #1, table Default-IP-Routing-Table)
  Not advertised to any peer
  Local
  10.1.1.2 (metric 20) from 10.1.1.2 (10.1.1.2)
    Origin IGP, metric 0, localpref 100, valid, internal, best
    Community: 1:1 1:2 1:3 20:1 20:2 20:3 99:1
    Last update: Wed Mar 4 13:50:36 2015

qct-ly6-04#

We apply the following FOO route-map inbound to this peer and soft clear the peer
!
ip community-list expanded BAD_COMMS permit 99:.*
ip community-list expanded BAD_COMMS deny 1:.*
ip community-list expanded BAD_COMMS permit 20.*
!
route-map FOO permit 10
set comm-list BAD_COMMS delete
!
router bgp 10
neighbor 10.1.1.2 route-map FOO in
!

qct-ly6-04# clear ip bgp * soft in
qct-ly6-04# show ip bgp 10.1.3.0/24
  BGP routing table entry for 10.1.3.0/24
  Paths: (1 available, best #1, table Default-IP-Routing-Table)
  Not advertised to any peer
  Local
  10.1.1.2 (metric 20) from 10.1.1.2 (10.1.1.2)
    Origin IGP, metric 0, localpref 100, valid, internal, best
    Community: 1:1 1:2 1:3
    Last update: Wed Mar 4 13:51:12 2015

qct-ly6-04#
qct-ly6-04#

We deleted all communities flagged as "permit" by the BAD_COMMS community-list
while leaving the ones matched by "deny 1:.*" alone.
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index 1bd2dd8..f1997bd 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -144,7 +144,7 @@
   return 0;
 }
 
-static u_int32_t
+u_int32_t
 community_val_get (struct community *com, int i)
 {
   u_char *p;