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 (
"strings"
)
const (
WellKnownCommunityNoExport = 0xFFFFFF01
WellKnownCommunityNoAdvertise = 0xFFFFFF02
)
func CommunityStringForUint32(v uint32) string {
e1 := v >> 16
e2 := v - e1<<16
......
......@@ -723,6 +723,7 @@ func (fsm *FSM) established() int {
n := &routingtable.Neighbor{
Type: route.BGPPathType,
Address: tnet.IPv4ToUint32(fsm.remote),
IBGP: fsm.remoteASN == fsm.localASN,
}
clientOptions := routingtable.ClientOptions{
......
......@@ -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.
func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error {
if a.isOwnPath(p) {
if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return nil
}
......@@ -56,7 +56,7 @@ func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error {
// RemovePath removes the path for prefix `pfx`
func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool {
if a.isOwnPath(p) {
if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return false
}
......@@ -77,19 +77,6 @@ func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool {
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) {
for _, path := range paths {
for _, client := range a.ClientManager.Clients() {
......
......@@ -37,7 +37,7 @@ func (a *AdjRIBOutAddPath) UpdateNewClient(client routingtable.RouteTableClient)
// AddPath adds path p to prefix `pfx`
func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
if a.isOwnPath(p) {
if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return nil
}
......@@ -63,7 +63,7 @@ func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
// RemovePath removes the path for prefix `pfx`
func (a *AdjRIBOutAddPath) RemovePath(pfx net.Prefix, p *route.Path) bool {
if a.isOwnPath(p) {
if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return false
}
......
......@@ -7,4 +7,7 @@ type Neighbor struct {
// Type is the type / protocol used for routing inforation communitation
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.
Finish editing this message first!
Please register or to comment