diff --git a/routingtable/filter/from.go b/routingtable/filter/from.go index 108253973493f499fc33dc5a3fe3d7b32d6e1d06..612122042cbaaa42f22ea756f7b38332b8e91b2b 100644 --- a/routingtable/filter/from.go +++ b/routingtable/filter/from.go @@ -6,11 +6,12 @@ import ( ) type From struct { - prefixLists []*PrefixList + prefixLists []*PrefixList + routeFilters []*RouteFilter } func (f *From) Matches(p net.Prefix, pa *route.Path) bool { - return f.matchesAnyPrefixList(p) + return f.matchesAnyPrefixList(p) || f.machtchesAnyRouteFilter(p) } func (t *From) matchesAnyPrefixList(p net.Prefix) bool { @@ -22,3 +23,13 @@ func (t *From) matchesAnyPrefixList(p net.Prefix) bool { return false } + +func (t *From) machtchesAnyRouteFilter(p net.Prefix) bool { + for _, l := range t.routeFilters { + if l.Matches(p) { + return true + } + } + + return false +} diff --git a/routingtable/filter/from_test.go b/routingtable/filter/from_test.go new file mode 100644 index 0000000000000000000000000000000000000000..acffa60a6e370502470f8449c3db80c732f9ad31 --- /dev/null +++ b/routingtable/filter/from_test.go @@ -0,0 +1,120 @@ +package filter + +import ( + "testing" + + "github.com/bio-routing/bio-rd/net" + "github.com/bio-routing/bio-rd/route" + "github.com/stretchr/testify/assert" +) + +func TestMatches(t *testing.T) { + tests := []struct { + name string + prefix net.Prefix + prefixLists []*PrefixList + routeFilters []*RouteFilter + expected bool + }{ + { + name: "one prefix matches in prefix list, no route filters set", + prefix: net.NewPfx(strAddr("127.0.0.1"), 8), + prefixLists: []*PrefixList{ + NewPrefixList(net.NewPfx(strAddr("127.0.0.1"), 8)), + }, + routeFilters: []*RouteFilter{}, + expected: true, + }, + { + name: "one prefix in prefix list and no match, no route filters set", + prefix: net.NewPfx(strAddr("127.0.0.1"), 8), + prefixLists: []*PrefixList{ + NewPrefixList(net.NewPfx(0, 32)), + }, + routeFilters: []*RouteFilter{}, + expected: false, + }, + { + name: "one prefix of 2 matches in prefix list, no route filters set", + prefix: net.NewPfx(strAddr("127.0.0.1"), 8), + prefixLists: []*PrefixList{ + NewPrefixList(net.NewPfx(strAddr("10.0.0.0"), 8)), + NewPrefixList(net.NewPfx(strAddr("127.0.0.1"), 8)), + }, + routeFilters: []*RouteFilter{}, + expected: true, + }, + { + name: "no prefixes in prefix list, only route filter matches", + prefix: net.NewPfx(strAddr("10.0.0.0"), 24), + prefixLists: []*PrefixList{}, + 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{}, + routeFilters: []*RouteFilter{ + NewRouteFilter(net.NewPfx(strAddr("8.0.0.0"), 8), Longer()), + NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()), + }, + 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{}, + routeFilters: []*RouteFilter{ + NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()), + }, + expected: false, + }, + { + name: "no match in prefix list, no macht in route filter", + prefix: net.NewPfx(strAddr("9.9.9.0"), 24), + prefixLists: []*PrefixList{ + NewPrefixList(net.NewPfx(strAddr("8.0.0.0"), 8)), + }, + routeFilters: []*RouteFilter{ + NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()), + }, + expected: false, + }, + { + name: "one prefix in prefixlist, one route fitler, only prefix list matches", + prefix: net.NewPfx(strAddr("8.8.8.0"), 24), + prefixLists: []*PrefixList{ + NewPrefixList(net.NewPfx(strAddr("8.0.0.0"), 8)), + }, + routeFilters: []*RouteFilter{ + NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()), + }, + expected: true, + }, + { + name: "one prefix in prefixlist, one route fitler, only route filter matches", + prefix: net.NewPfx(strAddr("10.0.0.0"), 24), + prefixLists: []*PrefixList{ + NewPrefixList(net.NewPfx(strAddr("8.0.0.0"), 8)), + }, + routeFilters: []*RouteFilter{ + NewRouteFilter(net.NewPfx(strAddr("10.0.0.0"), 8), Longer()), + }, + expected: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(te *testing.T) { + f := &From{ + prefixLists: test.prefixLists, + routeFilters: test.routeFilters, + } + + assert.Equal(te, test.expected, f.Matches(test.prefix, &route.Path{})) + }) + } +} diff --git a/routingtable/filter/prefix_list.go b/routingtable/filter/prefix_list.go index 8ccf36e8ab9820ad428604a08a5ded2cbcf03f91..91668160879d5416265ffe5304cf612c753f0819 100644 --- a/routingtable/filter/prefix_list.go +++ b/routingtable/filter/prefix_list.go @@ -4,21 +4,31 @@ import "github.com/bio-routing/bio-rd/net" type PrefixList struct { allowed []net.Prefix + matcher PrefixMatcher } func NewPrefixList(pfxs ...net.Prefix) *PrefixList { l := &PrefixList{ allowed: pfxs, + matcher: Exact(), + } + return l +} + +func NewPrefixListWithMatcher(matcher PrefixMatcher, pfxs ...net.Prefix) *PrefixList { + l := &PrefixList{ + allowed: pfxs, + matcher: matcher, } return l } func (l *PrefixList) Matches(p net.Prefix) bool { for _, a := range l.allowed { - if !a.Contains(p) { - return false + if a.Equal(p) { + return true } } - return true + return false } diff --git a/routingtable/filter/prefix_matcher.go b/routingtable/filter/prefix_matcher.go new file mode 100644 index 0000000000000000000000000000000000000000..8b6136b57bfadfe744cf151bae7454e5adb6f935 --- /dev/null +++ b/routingtable/filter/prefix_matcher.go @@ -0,0 +1,30 @@ +package filter + +import "github.com/bio-routing/bio-rd/net" + +type PrefixMatcher func(pattern, prefix net.Prefix) bool + +func InRange(min, max uint8) PrefixMatcher { + return func(pattern, prefix net.Prefix) bool { + contains := pattern.Equal(prefix) || pattern.Contains(prefix) + return contains && prefix.Pfxlen() >= min && prefix.Pfxlen() <= max + } +} + +func Exact() PrefixMatcher { + return func(pattern, prefix net.Prefix) bool { + return pattern.Equal(prefix) + } +} + +func OrLonger() PrefixMatcher { + return func(pattern, prefix net.Prefix) bool { + return pattern.Equal(prefix) || pattern.Contains(prefix) + } +} + +func Longer() PrefixMatcher { + return func(pattern, prefix net.Prefix) bool { + return pattern.Contains(prefix) && prefix.Pfxlen() > pattern.Pfxlen() + } +} diff --git a/routingtable/filter/route_filter.go b/routingtable/filter/route_filter.go index 78a922fef4792f321d1563689a2b38ac5391f859..d6716b5100166e755cc0950e7ba9bc6e8f0e1ae6 100644 --- a/routingtable/filter/route_filter.go +++ b/routingtable/filter/route_filter.go @@ -9,33 +9,6 @@ type RouteFilter struct { matcher PrefixMatcher } -type PrefixMatcher func(pattern, prefix net.Prefix) bool - -func InRange(min, max uint8) PrefixMatcher { - return func(pattern, prefix net.Prefix) bool { - contains := pattern.Equal(prefix) || pattern.Contains(prefix) - return contains && prefix.Pfxlen() >= min && prefix.Pfxlen() <= max - } -} - -func Exact() PrefixMatcher { - return func(pattern, prefix net.Prefix) bool { - return pattern.Equal(prefix) - } -} - -func OrLonger() PrefixMatcher { - return func(pattern, prefix net.Prefix) bool { - return pattern.Equal(prefix) || pattern.Contains(prefix) - } -} - -func Longer() PrefixMatcher { - return func(pattern, prefix net.Prefix) bool { - return pattern.Contains(prefix) && prefix.Pfxlen() > pattern.Pfxlen() - } -} - func NewRouteFilter(pattern net.Prefix, matcher PrefixMatcher) *RouteFilter { return &RouteFilter{ pattern: pattern, diff --git a/routingtable/filter/term_test.go b/routingtable/filter/term_test.go index bf045323e5221a43f8ed8643fab0b6ad8acf91f3..9720dbe3902d6edcb9c7eff2d04fdce7f83c6045 100644 --- a/routingtable/filter/term_test.go +++ b/routingtable/filter/term_test.go @@ -46,8 +46,8 @@ func TestProcess(t *testing.T) { path: &route.Path{}, from: []*From{ { - []*PrefixList{ - NewPrefixList(net.NewPfx(0, 0)), + prefixLists: []*PrefixList{ + NewPrefixList(net.NewPfx(strAddr("100.64.0.1"), 8)), }, }, }, @@ -63,7 +63,7 @@ func TestProcess(t *testing.T) { path: &route.Path{}, from: []*From{ { - []*PrefixList{ + prefixLists: []*PrefixList{ NewPrefixList(net.NewPfx(0, 32)), }, }, @@ -80,8 +80,8 @@ func TestProcess(t *testing.T) { path: &route.Path{}, from: []*From{ { - []*PrefixList{ - NewPrefixList(net.NewPfx(0, 0)), + prefixLists: []*PrefixList{ + NewPrefixList(net.NewPfx(strAddr("100.64.0.1"), 8)), }, }, }, @@ -97,8 +97,8 @@ func TestProcess(t *testing.T) { path: &route.Path{}, from: []*From{ { - []*PrefixList{ - NewPrefixList(net.NewPfx(0, 0)), + prefixLists: []*PrefixList{ + NewPrefixList(net.NewPfx(strAddr("100.64.0.1"), 8)), }, }, }, @@ -115,9 +115,9 @@ func TestProcess(t *testing.T) { path: &route.Path{}, from: []*From{ { - []*PrefixList{ - NewPrefixList(net.NewPfx(0, 32)), - NewPrefixList(net.NewPfx(0, 0)), + prefixLists: []*PrefixList{ + NewPrefixListWithMatcher(Exact(), net.NewPfx(0, 32)), + NewPrefixList(net.NewPfx(strAddr("100.64.0.1"), 8)), }, }, },