Skip to content
Snippets Groups Projects
Commit b9a06317 authored by Daniel Czerwonk's avatar Daniel Czerwonk
Browse files

basic rfc1997 (well known communities) filter, code deduplication

parent 8916eda2
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,11 @@ import ( ...@@ -6,6 +6,11 @@ import (
"strings" "strings"
) )
const (
WellKnownCommunityNoExport = 0xFFFFFF01
WellKnownCommunityNoAdvertise = 0xFFFFFF02
)
func CommunityStringForUint32(v uint32) string { func CommunityStringForUint32(v uint32) string {
e1 := v >> 16 e1 := v >> 16
e2 := v - e1<<16 e2 := v - e1<<16
......
...@@ -723,6 +723,7 @@ func (fsm *FSM) established() int { ...@@ -723,6 +723,7 @@ func (fsm *FSM) established() int {
n := &routingtable.Neighbor{ n := &routingtable.Neighbor{
Type: route.BGPPathType, Type: route.BGPPathType,
Address: tnet.IPv4ToUint32(fsm.remote), Address: tnet.IPv4ToUint32(fsm.remote),
IBGP: fsm.remoteASN == fsm.localASN,
} }
clientOptions := routingtable.ClientOptions{ clientOptions := routingtable.ClientOptions{
......
...@@ -35,7 +35,7 @@ func (a *AdjRIBOut) UpdateNewClient(client routingtable.RouteTableClient) error ...@@ -35,7 +35,7 @@ func (a *AdjRIBOut) UpdateNewClient(client routingtable.RouteTableClient) error
// AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added. // AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added.
func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error { func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error {
if a.isOwnPath(p) { if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return nil return nil
} }
...@@ -56,7 +56,7 @@ func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error { ...@@ -56,7 +56,7 @@ func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error {
// RemovePath removes the path for prefix `pfx` // RemovePath removes the path for prefix `pfx`
func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool { func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool {
if a.isOwnPath(p) { if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return false return false
} }
...@@ -77,19 +77,6 @@ func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool { ...@@ -77,19 +77,6 @@ func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool {
return true return true
} }
func (a *AdjRIBOut) isOwnPath(p *route.Path) bool {
if p.Type != a.neighbor.Type {
return false
}
switch p.Type {
case route.BGPPathType:
return p.BGPPath.Source == a.neighbor.Address
}
return false
}
func (a *AdjRIBOut) removePathsFromClients(pfx net.Prefix, paths []*route.Path) { func (a *AdjRIBOut) removePathsFromClients(pfx net.Prefix, paths []*route.Path) {
for _, path := range paths { for _, path := range paths {
for _, client := range a.ClientManager.Clients() { for _, client := range a.ClientManager.Clients() {
......
...@@ -37,7 +37,7 @@ func (a *AdjRIBOutAddPath) UpdateNewClient(client routingtable.RouteTableClient) ...@@ -37,7 +37,7 @@ func (a *AdjRIBOutAddPath) UpdateNewClient(client routingtable.RouteTableClient)
// AddPath adds path p to prefix `pfx` // AddPath adds path p to prefix `pfx`
func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error { func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
if a.isOwnPath(p) { if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return nil return nil
} }
...@@ -63,7 +63,7 @@ func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error { ...@@ -63,7 +63,7 @@ func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
// RemovePath removes the path for prefix `pfx` // RemovePath removes the path for prefix `pfx`
func (a *AdjRIBOutAddPath) RemovePath(pfx net.Prefix, p *route.Path) bool { func (a *AdjRIBOutAddPath) RemovePath(pfx net.Prefix, p *route.Path) bool {
if a.isOwnPath(p) { if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return false return false
} }
......
...@@ -7,4 +7,7 @@ type Neighbor struct { ...@@ -7,4 +7,7 @@ type Neighbor struct {
// Type is the type / protocol used for routing inforation communitation // Type is the type / protocol used for routing inforation communitation
Type uint8 Type uint8
// IBGP returns if local ASN is equal to remote ASN
IBGP bool
} }
package routingtable
import (
"strings"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/route"
log "github.com/sirupsen/logrus"
)
// ShouldPropagateUpdate performs some default checks and returns if an route update should be propagated to a neighbor
func ShouldPropagateUpdate(pfx net.Prefix, p *route.Path, n *Neighbor) bool {
return !isOwnPath(p, n) && !isDisallowedByCommunity(p, n)
}
func isOwnPath(p *route.Path, n *Neighbor) bool {
if p.Type != n.Type {
return false
}
switch p.Type {
case route.BGPPathType:
return p.BGPPath.Source == n.Address
}
return false
}
func isDisallowedByCommunity(p *route.Path, n *Neighbor) bool {
if p.BGPPath == nil || len(p.BGPPath.Communities) == 0 {
return false
}
strs := strings.Split(p.BGPPath.Communities, " ")
for _, str := range strs {
com, err := packet.ParseCommunityString(str)
if err != nil {
log.WithField("Sender", "routingtable.ShouldAnnounce()").
WithField("community", str).
WithError(err).
Error("Could not parse community")
continue
}
if (com == packet.WellKnownCommunityNoExport && !n.IBGP) || com == packet.WellKnownCommunityNoAdvertise {
return true
}
}
return false
}
package routingtable
import (
"net"
"testing"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/stretchr/testify/assert"
)
func TestShouldPropagateUpdate(t *testing.T) {
tests := []struct {
name string
communities string
neighbor Neighbor
expected bool
}{
{
name: "arbitrary path",
expected: true,
},
{
name: "path was received from this peer before",
communities: "(1,2)",
neighbor: Neighbor{
Type: route.BGPPathType,
Address: bnet.IPv4ToUint32(net.ParseIP("192.168.1.1")),
},
expected: false,
},
{
name: "path with no-export community",
communities: "(1,2) (65535,65281)",
expected: false,
},
{
name: "path with no-export community (iBGP)",
communities: "(1,2) (65535,65281)",
neighbor: Neighbor{
IBGP: true,
},
expected: true,
},
{
name: "path with no-advertise community",
communities: "(1,2) (65535,65282)",
expected: false,
},
{
name: "path with no-advertise community (iBGP)",
communities: "(1,2) (65535,65282)",
neighbor: Neighbor{
IBGP: true,
},
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(te *testing.T) {
pfx := bnet.NewPfx(0, 32)
pa := &route.Path{
Type: route.BGPPathType,
BGPPath: &route.BGPPath{
Communities: test.communities,
Source: bnet.IPv4ToUint32(net.ParseIP("192.168.1.1")),
},
}
res := ShouldPropagateUpdate(pfx, pa, &test.neighbor)
assert.Equal(te, test.expected, res)
})
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment