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

Merge pull request #98 from bio-routing/fix/accept_did_not_terminate

Bugfix in Filter Action processing
parents 86f17a1f 6d5dbf0b
No related branches found
No related tags found
No related merge requests found
Showing
with 109 additions and 57 deletions
...@@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") ...@@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"action.go",
"community_filter.go", "community_filter.go",
"filter.go", "filter.go",
"helper.go", "helper.go",
......
package filter
import (
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable/filter/actions"
)
// Action performs actions on a `route.Path`
type Action interface {
Do(p net.Prefix, pa *route.Path) actions.Result
}
...@@ -4,10 +4,10 @@ go_library( ...@@ -4,10 +4,10 @@ go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"accept_action.go", "accept_action.go",
"action.go",
"add_community_action.go", "add_community_action.go",
"add_large_community_action.go", "add_large_community_action.go",
"as_path_prepend_action.go", "as_path_prepend_action.go",
"filter_action.go",
"reject_action.go", "reject_action.go",
"set_local_pref_action.go", "set_local_pref_action.go",
"set_nexthop_action.go", "set_nexthop_action.go",
......
...@@ -8,6 +8,9 @@ import ( ...@@ -8,6 +8,9 @@ import (
type AcceptAction struct { type AcceptAction struct {
} }
func (*AcceptAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { func (*AcceptAction) Do(p net.Prefix, pa *route.Path) Result {
return pa, false return Result{
Path: pa,
Terminate: true,
}
} }
package actions package actions
import ( import (
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/route"
) )
type FilterAction interface { type Result struct {
Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) Path *route.Path
Reject bool
Terminate bool
} }
...@@ -15,9 +15,9 @@ func NewAddCommunityAction(coms []uint32) *AddCommunityAction { ...@@ -15,9 +15,9 @@ func NewAddCommunityAction(coms []uint32) *AddCommunityAction {
} }
} }
func (a *AddCommunityAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { func (a *AddCommunityAction) Do(p net.Prefix, pa *route.Path) Result {
if pa.BGPPath == nil || len(a.communities) == 0 { if pa.BGPPath == nil || len(a.communities) == 0 {
return pa, false return Result{Path: pa}
} }
modified := pa.Copy() modified := pa.Copy()
...@@ -26,5 +26,5 @@ func (a *AddCommunityAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Pa ...@@ -26,5 +26,5 @@ func (a *AddCommunityAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Pa
modified.BGPPath.Communities = append(modified.BGPPath.Communities, com) modified.BGPPath.Communities = append(modified.BGPPath.Communities, com)
} }
return modified, false return Result{Path: modified}
} }
...@@ -53,9 +53,9 @@ func TestAddingCommunities(t *testing.T) { ...@@ -53,9 +53,9 @@ func TestAddingCommunities(t *testing.T) {
} }
a := NewAddCommunityAction(test.communities) a := NewAddCommunityAction(test.communities)
modPath, _ := a.Do(net.Prefix{}, p) res := a.Do(net.Prefix{}, p)
assert.Equal(t, test.expected, modPath.BGPPath.CommunitiesString()) assert.Equal(t, test.expected, res.Path.BGPPath.CommunitiesString())
}) })
} }
} }
...@@ -16,13 +16,13 @@ func NewAddLargeCommunityAction(coms []types.LargeCommunity) *AddLargeCommunityA ...@@ -16,13 +16,13 @@ func NewAddLargeCommunityAction(coms []types.LargeCommunity) *AddLargeCommunityA
} }
} }
func (a *AddLargeCommunityAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { func (a *AddLargeCommunityAction) Do(p net.Prefix, pa *route.Path) Result {
if pa.BGPPath == nil || len(a.communities) == 0 { if pa.BGPPath == nil || len(a.communities) == 0 {
return pa, false return Result{Path: pa}
} }
modified := pa.Copy() modified := pa.Copy()
modified.BGPPath.LargeCommunities = append(modified.BGPPath.LargeCommunities, a.communities...) modified.BGPPath.LargeCommunities = append(modified.BGPPath.LargeCommunities, a.communities...)
return modified, false return Result{Path: modified}
} }
...@@ -71,7 +71,7 @@ func TestAddingLargeCommunities(t *testing.T) { ...@@ -71,7 +71,7 @@ func TestAddingLargeCommunities(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(te *testing.T) { t.Run(test.name, func(t *testing.T) {
p := &route.Path{ p := &route.Path{
BGPPath: &route.BGPPath{ BGPPath: &route.BGPPath{
LargeCommunities: test.current, LargeCommunities: test.current,
...@@ -79,9 +79,9 @@ func TestAddingLargeCommunities(t *testing.T) { ...@@ -79,9 +79,9 @@ func TestAddingLargeCommunities(t *testing.T) {
} }
a := NewAddLargeCommunityAction(test.communities) a := NewAddLargeCommunityAction(test.communities)
modPath, _ := a.Do(net.Prefix{}, p) res := a.Do(net.Prefix{}, p)
assert.Equal(te, test.expected, modPath.BGPPath.LargeCommunitiesString()) assert.Equal(t, test.expected, res.Path.BGPPath.LargeCommunitiesString())
}) })
} }
} }
...@@ -17,13 +17,13 @@ func NewASPathPrependAction(asn uint32, times uint16) *ASPathPrependAction { ...@@ -17,13 +17,13 @@ func NewASPathPrependAction(asn uint32, times uint16) *ASPathPrependAction {
} }
} }
func (a *ASPathPrependAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { func (a *ASPathPrependAction) Do(p net.Prefix, pa *route.Path) Result {
if pa.BGPPath == nil { if pa.BGPPath == nil {
return pa, false return Result{Path: pa}
} }
modified := pa.Copy() modified := pa.Copy()
modified.BGPPath.Prepend(a.asn, a.times) modified.BGPPath.Prepend(a.asn, a.times)
return modified, false return Result{Path: modified}
} }
...@@ -54,9 +54,9 @@ func TestAppendPath(t *testing.T) { ...@@ -54,9 +54,9 @@ func TestAppendPath(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(te *testing.T) { t.Run(test.name, func(t *testing.T) {
a := NewASPathPrependAction(12345, test.times) a := NewASPathPrependAction(12345, test.times)
p, _ := a.Do(bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{ res := a.Do(bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{
BGPPath: test.bgpPath, BGPPath: test.bgpPath,
}) })
...@@ -64,8 +64,8 @@ func TestAppendPath(t *testing.T) { ...@@ -64,8 +64,8 @@ func TestAppendPath(t *testing.T) {
return return
} }
assert.Equal(te, test.expectedPath, p.BGPPath.ASPath.String(), "ASPath") assert.Equal(t, test.expectedPath, res.Path.BGPPath.ASPath.String(), "ASPath")
assert.Equal(te, test.expectedLength, p.BGPPath.ASPathLen, "ASPathLen") assert.Equal(t, test.expectedLength, res.Path.BGPPath.ASPathLen, "ASPathLen")
}) })
} }
} }
...@@ -8,6 +8,10 @@ import ( ...@@ -8,6 +8,10 @@ import (
type RejectAction struct { type RejectAction struct {
} }
func (*RejectAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { func (*RejectAction) Do(p net.Prefix, pa *route.Path) Result {
return pa, true return Result{
Path: pa,
Reject: true,
Terminate: true,
}
} }
...@@ -15,13 +15,13 @@ func NewSetLocalPrefAction(pref uint32) *SetLocalPrefAction { ...@@ -15,13 +15,13 @@ func NewSetLocalPrefAction(pref uint32) *SetLocalPrefAction {
} }
} }
func (a *SetLocalPrefAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { func (a *SetLocalPrefAction) Do(p net.Prefix, pa *route.Path) Result {
if pa.BGPPath == nil { if pa.BGPPath == nil {
return pa, false return Result{Path: pa}
} }
modified := *pa modified := *pa
modified.BGPPath.LocalPref = a.pref modified.BGPPath.LocalPref = a.pref
return &modified, false return Result{Path: &modified}
} }
...@@ -27,14 +27,14 @@ func TestSetLocalPref(t *testing.T) { ...@@ -27,14 +27,14 @@ func TestSetLocalPref(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(te *testing.T) { t.Run(test.name, func(t *testing.T) {
a := NewSetLocalPrefAction(150) a := NewSetLocalPrefAction(150)
p, _ := a.Do(bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{ res := a.Do(bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{
BGPPath: test.bgpPath, BGPPath: test.bgpPath,
}) })
if test.expectedLocalPref > 0 { if test.expectedLocalPref > 0 {
assert.Equal(te, test.expectedLocalPref, p.BGPPath.LocalPref) assert.Equal(t, test.expectedLocalPref, res.Path.BGPPath.LocalPref)
} }
}) })
} }
......
...@@ -16,13 +16,13 @@ func NewSetNextHopAction(ip bnet.IP) *SetNextHopAction { ...@@ -16,13 +16,13 @@ func NewSetNextHopAction(ip bnet.IP) *SetNextHopAction {
} }
} }
func (a *SetNextHopAction) Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { func (a *SetNextHopAction) Do(p net.Prefix, pa *route.Path) Result {
if pa.BGPPath == nil { if pa.BGPPath == nil {
return pa, false return Result{Path: pa}
} }
modified := pa.Copy() modified := pa.Copy()
modified.BGPPath.NextHop = a.ip modified.BGPPath.NextHop = a.ip
return modified, false return Result{Path: modified}
} }
...@@ -31,12 +31,12 @@ func TestSetNextHopTest(t *testing.T) { ...@@ -31,12 +31,12 @@ func TestSetNextHopTest(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
a := NewSetNextHopAction(bnet.IPv4FromOctets(100, 64, 2, 1)) a := NewSetNextHopAction(bnet.IPv4FromOctets(100, 64, 2, 1))
p, _ := a.Do(net.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{ res := a.Do(net.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{
BGPPath: test.bgpPath, BGPPath: test.bgpPath,
}) })
if test.bgpPath != nil { if test.bgpPath != nil {
assert.Equal(t, test.expected, p.BGPPath.NextHop) assert.Equal(t, test.expected, res.Path.BGPPath.NextHop)
} }
}) })
} }
......
...@@ -21,10 +21,11 @@ func (f *Filter) ProcessTerms(p net.Prefix, pa *route.Path) (modPath *route.Path ...@@ -21,10 +21,11 @@ func (f *Filter) ProcessTerms(p net.Prefix, pa *route.Path) (modPath *route.Path
modPath = pa modPath = pa
for _, t := range f.terms { for _, t := range f.terms {
modPath, reject = t.Process(p, modPath) res := t.Process(p, modPath)
if reject { if res.Terminate {
return modPath, true return res.Path, res.Reject
} }
modPath = res.Path
} }
return modPath, false return modPath, false
......
...@@ -23,7 +23,7 @@ func TestProcessTerms(t *testing.T) { ...@@ -23,7 +23,7 @@ func TestProcessTerms(t *testing.T) {
prefix: net.NewPfx(net.IPv4(0), 0), prefix: net.NewPfx(net.IPv4(0), 0),
path: &route.Path{}, path: &route.Path{},
term: &Term{ term: &Term{
then: []FilterAction{ then: []Action{
&actions.AcceptAction{}, &actions.AcceptAction{},
}, },
}, },
...@@ -35,19 +35,32 @@ func TestProcessTerms(t *testing.T) { ...@@ -35,19 +35,32 @@ func TestProcessTerms(t *testing.T) {
prefix: net.NewPfx(net.IPv4(0), 0), prefix: net.NewPfx(net.IPv4(0), 0),
path: &route.Path{}, path: &route.Path{},
term: &Term{ term: &Term{
then: []FilterAction{ then: []Action{
&actions.RejectAction{}, &actions.RejectAction{},
}, },
}, },
exptectAccept: false, exptectAccept: false,
expectModified: false, expectModified: false,
}, },
{
name: "accept before reject",
prefix: net.NewPfx(net.IPv4(0), 0),
path: &route.Path{},
term: &Term{
then: []Action{
&actions.AcceptAction{},
&actions.RejectAction{},
},
},
exptectAccept: true,
expectModified: false,
},
{ {
name: "modified", name: "modified",
prefix: net.NewPfx(net.IPv4(0), 0), prefix: net.NewPfx(net.IPv4(0), 0),
path: &route.Path{}, path: &route.Path{},
term: &Term{ term: &Term{
then: []FilterAction{ then: []Action{
&mockAction{}, &mockAction{},
&actions.AcceptAction{}, &actions.AcceptAction{},
}, },
...@@ -58,7 +71,7 @@ func TestProcessTerms(t *testing.T) { ...@@ -58,7 +71,7 @@ func TestProcessTerms(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(te *testing.T) { t.Run(test.name, func(t *testing.T) {
f := NewFilter([]*Term{test.term}) f := NewFilter([]*Term{test.term})
p, reject := f.ProcessTerms(test.prefix, test.path) p, reject := f.ProcessTerms(test.prefix, test.path)
......
...@@ -10,7 +10,7 @@ func NewAcceptAllFilter() *Filter { ...@@ -10,7 +10,7 @@ func NewAcceptAllFilter() *Filter {
[]*Term{ []*Term{
NewTerm( NewTerm(
[]*TermCondition{}, []*TermCondition{},
[]FilterAction{ []Action{
&actions.AcceptAction{}, &actions.AcceptAction{},
}), }),
}) })
...@@ -22,7 +22,7 @@ func NewDrainFilter() *Filter { ...@@ -22,7 +22,7 @@ func NewDrainFilter() *Filter {
[]*Term{ []*Term{
NewTerm( NewTerm(
[]*TermCondition{}, []*TermCondition{},
[]FilterAction{ []Action{
&actions.RejectAction{}, &actions.RejectAction{},
}), }),
}) })
......
...@@ -5,18 +5,20 @@ import ( ...@@ -5,18 +5,20 @@ import (
"github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/route"
) )
type FilterAction interface {
Do(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool)
}
// Term matches a path against a list of conditions and performs actions if it matches // Term matches a path against a list of conditions and performs actions if it matches
type Term struct { type Term struct {
from []*TermCondition from []*TermCondition
then []FilterAction then []Action
}
type TermResult struct {
Path *route.Path
Terminate bool
Reject bool
} }
// NewTerm creates a new term // NewTerm creates a new term
func NewTerm(from []*TermCondition, then []FilterAction) *Term { func NewTerm(from []*TermCondition, then []Action) *Term {
t := &Term{ t := &Term{
from: from, from: from,
then: then, then: then,
...@@ -26,7 +28,7 @@ func NewTerm(from []*TermCondition, then []FilterAction) *Term { ...@@ -26,7 +28,7 @@ func NewTerm(from []*TermCondition, then []FilterAction) *Term {
} }
// Process processes a path returning if the path should be rejected and returns a possible modified version of the path // Process processes a path returning if the path should be rejected and returns a possible modified version of the path
func (t *Term) Process(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { func (t *Term) Process(p net.Prefix, pa *route.Path) TermResult {
orig := pa orig := pa
if len(t.from) == 0 { if len(t.from) == 0 {
...@@ -39,18 +41,23 @@ func (t *Term) Process(p net.Prefix, pa *route.Path) (modPath *route.Path, rejec ...@@ -39,18 +41,23 @@ func (t *Term) Process(p net.Prefix, pa *route.Path) (modPath *route.Path, rejec
} }
} }
return orig, false return TermResult{Path: orig}
} }
func (t *Term) processActions(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { func (t *Term) processActions(p net.Prefix, pa *route.Path) TermResult {
modPath = pa modPath := pa
for _, action := range t.then { for _, action := range t.then {
modPath, reject = action.Do(p, modPath) res := action.Do(p, modPath)
if reject { if res.Terminate {
continue return TermResult{
Path: modPath,
Terminate: true,
Reject: res.Reject,
}
} }
modPath = res.Path
} }
return modPath, reject return TermResult{Path: modPath}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment