Skip to content
Snippets Groups Projects
Unverified Commit ec587cf4 authored by takt's avatar takt Committed by GitHub
Browse files

Merge pull request #39 from bio-routing/feature/community_filters

Feature/community filters
parents 7fd338f8 c8a05e1d
No related branches found
No related tags found
No related merge requests found
......@@ -13,7 +13,7 @@ const (
func CommunityStringForUint32(v uint32) string {
e1 := v >> 16
e2 := v - e1<<16
e2 := v & 0x0000FFFF
return fmt.Sprintf("(%d,%d)", e1, e2)
}
......
package actions
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"
)
type AddCommunityAction struct {
communities []uint32
}
func NewAddCommunityAction(coms []uint32) *AddCommunityAction {
return &AddCommunityAction{
communities: coms,
}
}
func (a *AddCommunityAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) {
if pa.BGPPath == nil || len(a.communities) == 0 {
return pa, false
}
modified := pa.Copy()
for _, com := range a.communities {
modified.BGPPath.Communities = modified.BGPPath.Communities + " " + packet.CommunityStringForUint32(com)
}
modified.BGPPath.Communities = strings.TrimLeft(modified.BGPPath.Communities, " ")
return modified, false
}
package actions
import (
"testing"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/stretchr/testify/assert"
)
func TestAddingCommunities(t *testing.T) {
tests := []struct {
name string
current string
communities []uint32
expected string
}{
{
name: "add one to empty",
communities: []uint32{
65538,
},
expected: "(1,2)",
},
{
name: "add one to existing",
current: "(1,2)",
communities: []uint32{
196612,
},
expected: "(1,2) (3,4)",
},
{
name: "add two to existing",
current: "(1,2)",
communities: []uint32{
196612, 327686,
},
expected: "(1,2) (3,4) (5,6)",
},
}
for _, test := range tests {
t.Run(test.name, func(te *testing.T) {
p := &route.Path{
BGPPath: &route.BGPPath{
Communities: test.current,
},
}
a := NewAddCommunityAction(test.communities)
modPath, _ := a.Do(net.Prefix{}, p)
assert.Equal(te, test.expected, modPath.BGPPath.Communities)
})
}
}
package filter
import (
"strings"
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
)
type CommunityFilter struct {
community uint32
}
func (f *CommunityFilter) Matches(communityString string) bool {
return strings.Contains(communityString, packet.CommunityStringForUint32(f.community))
}
......@@ -8,6 +8,7 @@ import (
type TermCondition struct {
prefixLists []*PrefixList
routeFilters []*RouteFilter
communityFilters []*CommunityFilter
largeCommunityFilters []*LargeCommunityFilter
}
......@@ -19,10 +20,17 @@ func NewTermCondition(prefixLists []*PrefixList, routeFilters []*RouteFilter) *T
}
func (f *TermCondition) Matches(p net.Prefix, pa *route.Path) bool {
return f.matchesAnyPrefixList(p) || f.machtchesAnyRouteFilter(p) || f.machtchesAnyLageCommunityFilter(pa)
return f.matchesPrefixListFilters(p) &&
f.machtchesRouteFilters(p) &&
f.machtchesCommunityFilters(pa) &&
f.machtchesLargeCommunityFilters(pa)
}
func (t *TermCondition) matchesAnyPrefixList(p net.Prefix) bool {
func (t *TermCondition) matchesPrefixListFilters(p net.Prefix) bool {
if len(t.prefixLists) == 0 {
return true
}
for _, l := range t.prefixLists {
if l.Matches(p) {
return true
......@@ -32,7 +40,11 @@ func (t *TermCondition) matchesAnyPrefixList(p net.Prefix) bool {
return false
}
func (t *TermCondition) machtchesAnyRouteFilter(p net.Prefix) bool {
func (t *TermCondition) machtchesRouteFilters(p net.Prefix) bool {
if len(t.routeFilters) == 0 {
return true
}
for _, l := range t.routeFilters {
if l.Matches(p) {
return true
......@@ -42,7 +54,29 @@ func (t *TermCondition) machtchesAnyRouteFilter(p net.Prefix) bool {
return false
}
func (t *TermCondition) machtchesAnyLageCommunityFilter(pa *route.Path) bool {
func (t *TermCondition) machtchesCommunityFilters(pa *route.Path) bool {
if len(t.communityFilters) == 0 {
return true
}
if pa.BGPPath == nil {
return false
}
for _, l := range t.communityFilters {
if l.Matches(pa.BGPPath.Communities) {
return true
}
}
return false
}
func (t *TermCondition) machtchesLargeCommunityFilters(pa *route.Path) bool {
if len(t.largeCommunityFilters) == 0 {
return true
}
if pa.BGPPath == nil {
return false
}
......
......@@ -16,6 +16,7 @@ func TestMatches(t *testing.T) {
bgpPath *route.BGPPath
prefixLists []*PrefixList
routeFilters []*RouteFilter
communityFilters []*CommunityFilter
largeCommunityFilters []*LargeCommunityFilter
expected bool
}{
......@@ -25,8 +26,7 @@ func TestMatches(t *testing.T) {
prefixLists: []*PrefixList{
NewPrefixList(net.NewPfx(strAddr("127.0.0.1"), 8)),
},
routeFilters: []*RouteFilter{},
expected: true,
expected: true,
},
{
name: "one prefix in prefix list and no match, no route filters set",
......@@ -34,8 +34,7 @@ func TestMatches(t *testing.T) {
prefixLists: []*PrefixList{
NewPrefixList(net.NewPfx(0, 32)),
},
routeFilters: []*RouteFilter{},
expected: false,
expected: false,
},
{
name: "one prefix of 2 matches in prefix list, no route filters set",
......@@ -44,22 +43,19 @@ func TestMatches(t *testing.T) {
NewPrefixList(net.NewPfx(strAddr("10.0.0.0"), 8)),
NewPrefixList(net.NewPfx(strAddr("127.0.0.1"), 8)),
},
routeFilters: []*RouteFilter{},
expected: true,
expected: true,
},
{
name: "no prefixes in prefix list, only route filter matches",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
prefixLists: []*PrefixList{},
name: "no prefixes in prefix list, only route filter matches",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
routeFilters: []*RouteFilter{
NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()),
},
expected: true,
},
{
name: "no prefixes in prefix list, one route filter matches",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
prefixLists: []*PrefixList{},
name: "no prefixes in prefix list, one route filter matches",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
routeFilters: []*RouteFilter{
NewRouteFilter(net.NewPfx(strAddr("8.0.0.0"), 8), Longer()),
NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()),
......@@ -67,9 +63,8 @@ func TestMatches(t *testing.T) {
expected: true,
},
{
name: "no prefixes in prefix list, one of many route filters matches",
prefix: net.NewPfx(strAddr("127.0.0.1"), 8),
prefixLists: []*PrefixList{},
name: "no prefixes in prefix list, one of many route filters matches",
prefix: net.NewPfx(strAddr("127.0.0.1"), 8),
routeFilters: []*RouteFilter{
NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()),
},
......@@ -87,7 +82,7 @@ func TestMatches(t *testing.T) {
expected: false,
},
{
name: "one prefix in prefixlist, one route fitler, only prefix list matches",
name: "one prefix in prefixlist, one route filter, only prefix list matches",
prefix: net.NewPfx(strAddr("8.8.8.0"), 24),
prefixLists: []*PrefixList{
NewPrefixList(net.NewPfx(strAddr("8.0.0.0"), 8)),
......@@ -95,10 +90,10 @@ func TestMatches(t *testing.T) {
routeFilters: []*RouteFilter{
NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()),
},
expected: true,
expected: false,
},
{
name: "one prefix in prefixlist, one route fitler, only route filter matches",
name: "one prefix in prefixlist, one route filter, only route filter matches",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
prefixLists: []*PrefixList{
NewPrefixList(net.NewPfx(strAddr("8.0.0.0"), 8)),
......@@ -106,8 +101,38 @@ func TestMatches(t *testing.T) {
routeFilters: []*RouteFilter{
NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()),
},
expected: false,
},
{
name: "community matches",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
bgpPath: &route.BGPPath{
Communities: "(1,2) (3,4) (5,6)",
},
communityFilters: []*CommunityFilter{
&CommunityFilter{196612}, // (3,4)
},
expected: true,
},
{
name: "community does not match",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
bgpPath: &route.BGPPath{
Communities: "(1,2) (3,4) (5,6)",
},
communityFilters: []*CommunityFilter{
&CommunityFilter{196608}, // (3,0)
},
expected: false,
},
{
name: "community filter, bgp path is nil",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
communityFilters: []*CommunityFilter{
&CommunityFilter{196608}, // (3,0)
},
expected: false,
},
{
name: "large community matches",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
......@@ -140,11 +165,26 @@ func TestMatches(t *testing.T) {
},
expected: false,
},
{
name: "large community filter, bgp path is nil",
prefix: net.NewPfx(strAddr("10.0.0.0"), 24),
largeCommunityFilters: []*LargeCommunityFilter{
{
&packet.LargeCommunity{
GlobalAdministrator: 1,
DataPart1: 2,
DataPart2: 3,
},
},
},
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(te *testing.T) {
f := NewTermCondition(test.prefixLists, test.routeFilters)
f.communityFilters = test.communityFilters
f.largeCommunityFilters = test.largeCommunityFilters
pa := &route.Path{
......
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