diff --git a/config/peer.go b/config/peer.go index 245c1aa2c940a3e878c296748b3c79c62882d479..418d8e00488ddbdde0b6c2cb86b6bcd3e1153644 100644 --- a/config/peer.go +++ b/config/peer.go @@ -5,6 +5,7 @@ import ( "time" "github.com/bio-routing/bio-rd/routingtable" + "github.com/bio-routing/bio-rd/routingtable/filter" ) type Peer struct { @@ -20,4 +21,6 @@ type Peer struct { RouterID uint32 AddPathSend routingtable.ClientOptions AddPathRecv bool + ImportFilter *filter.Filter + ExportFilter *filter.Filter } diff --git a/main.go b/main.go index 49d19c0f0f76019ae6f522b5f82e0262b5ec99a9..f74f4a0d82aa55412b840ebb83fdecee76733c39 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "github.com/bio-routing/bio-rd/config" "github.com/bio-routing/bio-rd/protocols/bgp/server" "github.com/bio-routing/bio-rd/routingtable" + "github.com/bio-routing/bio-rd/routingtable/filter" "github.com/bio-routing/bio-rd/routingtable/locRIB" ) @@ -45,6 +46,8 @@ func main() { AddPathSend: routingtable.ClientOptions{ MaxPaths: 10, }, + ExportFilter: filter.NewAcceptAllFilter(), + ImportFilter: filter.NewDrainFilter(), }, rib) //time.Sleep(time.Second * 15) @@ -63,7 +66,9 @@ func main() { AddPathSend: routingtable.ClientOptions{ MaxPaths: 10, }, - AddPathRecv: true, + AddPathRecv: true, + ImportFilter: filter.NewDrainFilter(), + ExportFilter: filter.NewAcceptAllFilter(), }, rib) go func() { diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go index 87ef4ba1f935e8ae8068c2a63ce0789eb7db0bf7..e54e64533fea03560334370a7d47b7774934d98a 100644 --- a/protocols/bgp/server/fsm_established.go +++ b/protocols/bgp/server/fsm_established.go @@ -53,7 +53,9 @@ func (s establishedState) run() (state, string) { func (s *establishedState) init() { s.fsm.adjRIBIn = adjRIBIn.New() - s.fsm.adjRIBIn.Register(s.fsm.rib) + + s.fsm.peer.importFilter.Register(s.fsm.rib) + s.fsm.adjRIBIn.Register(s.fsm.peer.importFilter) n := &routingtable.Neighbor{ Type: route.BGPPathType, @@ -71,7 +73,8 @@ func (s *establishedState) init() { } s.fsm.adjRIBOut.Register(s.fsm.updateSender) - s.fsm.rib.RegisterWithOptions(s.fsm.adjRIBOut, clientOptions) + s.fsm.peer.exportFilter.Register(s.fsm.adjRIBOut) + s.fsm.rib.RegisterWithOptions(s.fsm.peer.exportFilter, clientOptions) s.fsm.ribsInitialized = true } diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go index 26f183ce7b7572f71a6edc6982122eccf88fccf2..a0e4c623b5d4d30bdb877311c879b7c568332859 100644 --- a/protocols/bgp/server/peer.go +++ b/protocols/bgp/server/peer.go @@ -96,6 +96,8 @@ func NewPeer(c config.Peer, rib routingtable.RouteTableClient, server *BGPServer keepaliveTime: c.KeepAlive, holdTime: c.HoldTime, optOpenParams: make([]packet.OptParam, 0), + importFilter: filterOrDefault(c.ImportFilter), + exportFilter: filterOrDefault(c.ExportFilter), } p.fsms = append(p.fsms, NewActiveFSM2(p)) @@ -130,6 +132,14 @@ func NewPeer(c config.Peer, rib routingtable.RouteTableClient, server *BGPServer return p, nil } +func filterOrDefault(f *filter.Filter) *filter.Filter { + if f != nil { + return f + } + + return filter.NewDrainFilter() +} + // GetAddr returns the IP address of the peer func (p *Peer) GetAddr() net.IP { return p.addr diff --git a/routingtable/filter/helper.go b/routingtable/filter/helper.go new file mode 100644 index 0000000000000000000000000000000000000000..17a7d73789d5be569bec1725592a35f1b3841386 --- /dev/null +++ b/routingtable/filter/helper.go @@ -0,0 +1,29 @@ +package filter + +import ( + "github.com/bio-routing/bio-rd/routingtable/filter/actions" +) + +// NewAcceptAllFilter returns a filter accepting any paths/prefixes +func NewAcceptAllFilter() *Filter { + return NewFilter( + []*Term{ + NewTerm( + []*TermCondition{}, + []FilterAction{ + &actions.AcceptAction{}, + }), + }) +} + +// NewDrainFilter returns a filter rejecting any paths/prefixes +func NewDrainFilter() *Filter { + return NewFilter( + []*Term{ + NewTerm( + []*TermCondition{}, + []FilterAction{ + &actions.RejectAction{}, + }), + }) +} diff --git a/routingtable/filter/helper_test.go b/routingtable/filter/helper_test.go new file mode 100644 index 0000000000000000000000000000000000000000..a0370e7677aa303dcc2efc5d0242f2f287222d9a --- /dev/null +++ b/routingtable/filter/helper_test.go @@ -0,0 +1,34 @@ +package filter + +import ( + "testing" + + "github.com/bio-routing/bio-rd/net" + "github.com/bio-routing/bio-rd/route" +) + +func TestNewAcceptAllFilter(t *testing.T) { + f := NewAcceptAllFilter() + + m := &clientMock{} + f.Register(m) + + f.AddPath(net.NewPfx(0, 0), &route.Path{}) + + if !m.addPathCalled { + t.Fatalf("expected accepted, but was filtered") + } +} + +func TestNewDrainFilter(t *testing.T) { + f := NewDrainFilter() + + m := &clientMock{} + f.Register(m) + + f.AddPath(net.NewPfx(0, 0), &route.Path{}) + + if m.addPathCalled { + t.Fatalf("expected filtered, but was accepted") + } +} diff --git a/routingtable/filter/term.go b/routingtable/filter/term.go index 0d546be8bc7ceaf07e12a85453ed5cce741ea3cd..d644acba4a977e67e757fc5c7f71863531427e12 100644 --- a/routingtable/filter/term.go +++ b/routingtable/filter/term.go @@ -39,7 +39,7 @@ func (t *Term) Process(p net.Prefix, pa *route.Path) (modPath *route.Path, rejec } } - return orig, true + return orig, false } func (t *Term) processActions(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) { diff --git a/routingtable/filter/term_condition.go b/routingtable/filter/term_condition.go index fe19e461701dc1a453a3ddee17a38547d08936a6..9839ebe65397cb13af7bf3943761a91c108409c5 100644 --- a/routingtable/filter/term_condition.go +++ b/routingtable/filter/term_condition.go @@ -19,6 +19,18 @@ func NewTermCondition(prefixLists []*PrefixList, routeFilters []*RouteFilter) *T } } +func NewTermConditionWithRouteFilters(filters ...*RouteFilter) *TermCondition { + return &TermCondition{ + routeFilters: filters, + } +} + +func NewTermConditionWithPrefixLists(filters ...*PrefixList) *TermCondition { + return &TermCondition{ + prefixLists: filters, + } +} + func (f *TermCondition) Matches(p net.Prefix, pa *route.Path) bool { return f.matchesPrefixListFilters(p) && f.machtchesRouteFilters(p) && diff --git a/routingtable/filter/term_test.go b/routingtable/filter/term_test.go index 967480e76cdaa8a81f7594651b83fa8405fe02f9..d3abef87b52d2679084827283744e9b73599b433 100644 --- a/routingtable/filter/term_test.go +++ b/routingtable/filter/term_test.go @@ -45,11 +45,8 @@ func TestProcess(t *testing.T) { prefix: net.NewPfx(strAddr("100.64.0.1"), 8), path: &route.Path{}, from: []*TermCondition{ - { - prefixLists: []*PrefixList{ - NewPrefixList(net.NewPfx(strAddr("100.64.0.1"), 8)), - }, - }, + NewTermConditionWithPrefixLists( + NewPrefixList(net.NewPfx(strAddr("100.64.0.1"), 8))), }, then: []FilterAction{ &actions.AcceptAction{}, @@ -62,16 +59,13 @@ func TestProcess(t *testing.T) { prefix: net.NewPfx(strAddr("100.64.0.1"), 8), path: &route.Path{}, from: []*TermCondition{ - { - prefixLists: []*PrefixList{ - NewPrefixList(net.NewPfx(0, 32)), - }, - }, + NewTermConditionWithPrefixLists( + NewPrefixList(net.NewPfx(0, 32))), }, then: []FilterAction{ &actions.AcceptAction{}, }, - expectReject: true, + expectReject: false, expectModified: false, }, { @@ -79,11 +73,8 @@ func TestProcess(t *testing.T) { prefix: net.NewPfx(strAddr("100.64.0.1"), 8), path: &route.Path{}, from: []*TermCondition{ - { - prefixLists: []*PrefixList{ - NewPrefixList(net.NewPfx(strAddr("100.64.0.1"), 8)), - }, - }, + NewTermConditionWithPrefixLists( + NewPrefixList(net.NewPfx(strAddr("100.64.0.1"), 8))), }, then: []FilterAction{ &mockAction{}, @@ -96,11 +87,8 @@ func TestProcess(t *testing.T) { prefix: net.NewPfx(strAddr("100.64.0.1"), 8), path: &route.Path{}, from: []*TermCondition{ - { - prefixLists: []*PrefixList{ - NewPrefixList(net.NewPfx(strAddr("100.64.0.1"), 8)), - }, - }, + NewTermConditionWithRouteFilters( + NewRouteFilter(net.NewPfx(strAddr("100.64.0.1"), 8), Exact())), }, then: []FilterAction{ &mockAction{},