summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--internal/pkg/table/roa.go273
-rw-r--r--internal/pkg/table/roa_test.go (renamed from pkg/server/rpki_test.go)103
-rw-r--r--pkg/server/rpki.go306
-rw-r--r--pkg/server/server.go23
4 files changed, 341 insertions, 364 deletions
diff --git a/internal/pkg/table/roa.go b/internal/pkg/table/roa.go
index fe08fe54..88f81705 100644
--- a/internal/pkg/table/roa.go
+++ b/internal/pkg/table/roa.go
@@ -18,6 +18,12 @@ package table
import (
"fmt"
"net"
+ "sort"
+
+ radix "github.com/armon/go-radix"
+ "github.com/osrg/gobgp/internal/pkg/config"
+ "github.com/osrg/gobgp/pkg/packet/bgp"
+ log "github.com/sirupsen/logrus"
)
type IPPrefix struct {
@@ -58,3 +64,270 @@ func (r *ROA) Equal(roa *ROA) bool {
}
return false
}
+
+type roaBucket struct {
+ Prefix *IPPrefix
+ entries []*ROA
+}
+
+func (r *roaBucket) GetEntries() []*ROA {
+ return r.entries
+}
+
+type ROATable struct {
+ Roas map[bgp.RouteFamily]*radix.Tree
+}
+
+func NewROATable() *ROATable {
+ m := make(map[bgp.RouteFamily]*radix.Tree)
+ m[bgp.RF_IPv4_UC] = radix.New()
+ m[bgp.RF_IPv6_UC] = radix.New()
+ return &ROATable{
+ Roas: m,
+ }
+}
+
+func (rt *ROATable) roa2tree(roa *ROA) (*radix.Tree, string) {
+ tree := rt.Roas[bgp.RF_IPv4_UC]
+ if roa.Family == bgp.AFI_IP6 {
+ tree = rt.Roas[bgp.RF_IPv6_UC]
+ }
+ return tree, IpToRadixkey(roa.Prefix.Prefix, roa.Prefix.Length)
+}
+
+func (rt *ROATable) Add(roa *ROA) {
+ tree, key := rt.roa2tree(roa)
+ b, _ := tree.Get(key)
+ var bucket *roaBucket
+ if b == nil {
+ bucket = &roaBucket{
+ Prefix: roa.Prefix,
+ entries: make([]*ROA, 0),
+ }
+ tree.Insert(key, bucket)
+ } else {
+ bucket = b.(*roaBucket)
+ for _, r := range bucket.entries {
+ if r.Equal(roa) {
+ // we already have the same one
+ return
+ }
+ }
+ }
+ bucket.entries = append(bucket.entries, roa)
+}
+
+func (rt *ROATable) Delete(roa *ROA) {
+ tree, key := rt.roa2tree(roa)
+ b, _ := tree.Get(key)
+ if b != nil {
+ bucket := b.(*roaBucket)
+ newEntries := make([]*ROA, 0, len(bucket.entries))
+ for _, r := range bucket.entries {
+ if !r.Equal(roa) {
+ newEntries = append(newEntries, r)
+ }
+ }
+ if len(newEntries) != len(bucket.entries) {
+ bucket.entries = newEntries
+ if len(newEntries) == 0 {
+ tree.Delete(key)
+ }
+ return
+ }
+ }
+ log.WithFields(log.Fields{
+ "Topic": "rpki",
+ "Prefix": roa.Prefix.Prefix.String(),
+ "Prefix Length": roa.Prefix.Length,
+ "AS": roa.AS,
+ "Max Length": roa.MaxLen,
+ }).Info("Can't withdraw a ROA")
+}
+
+func (rt *ROATable) DeleteAll(network string) {
+ for _, tree := range rt.Roas {
+ deleteKeys := make([]string, 0, tree.Len())
+ tree.Walk(func(s string, v interface{}) bool {
+ b, _ := v.(*roaBucket)
+ newEntries := make([]*ROA, 0, len(b.entries))
+ for _, r := range b.entries {
+ if r.Src != network {
+ newEntries = append(newEntries, r)
+ }
+ }
+ if len(newEntries) > 0 {
+ b.entries = newEntries
+ } else {
+ deleteKeys = append(deleteKeys, s)
+ }
+ return false
+ })
+ for _, key := range deleteKeys {
+ tree.Delete(key)
+ }
+ }
+}
+
+func validatePath(ownAs uint32, tree *radix.Tree, cidr string, asPath *bgp.PathAttributeAsPath) *Validation {
+ var as uint32
+
+ validation := &Validation{
+ Status: config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND,
+ Reason: RPKI_VALIDATION_REASON_TYPE_NONE,
+ Matched: make([]*ROA, 0),
+ UnmatchedLength: make([]*ROA, 0),
+ UnmatchedAs: make([]*ROA, 0),
+ }
+
+ if asPath == nil || len(asPath.Value) == 0 {
+ as = ownAs
+ } else {
+ param := asPath.Value[len(asPath.Value)-1]
+ switch param.GetType() {
+ case bgp.BGP_ASPATH_ATTR_TYPE_SEQ:
+ asList := param.GetAS()
+ if len(asList) == 0 {
+ as = ownAs
+ } else {
+ as = asList[len(asList)-1]
+ }
+ case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
+ as = ownAs
+ default:
+ return validation
+ }
+ }
+ _, n, _ := net.ParseCIDR(cidr)
+ ones, _ := n.Mask.Size()
+ prefixLen := uint8(ones)
+ key := IpToRadixkey(n.IP, prefixLen)
+ _, b, _ := tree.LongestPrefix(key)
+ if b == nil {
+ return validation
+ }
+
+ var bucket *roaBucket
+ fn := radix.WalkFn(func(k string, v interface{}) bool {
+ bucket, _ = v.(*roaBucket)
+ for _, r := range bucket.entries {
+ if prefixLen <= r.MaxLen {
+ if r.AS != 0 && r.AS == as {
+ validation.Matched = append(validation.Matched, r)
+ } else {
+ validation.UnmatchedAs = append(validation.UnmatchedAs, r)
+ }
+ } else {
+ validation.UnmatchedLength = append(validation.UnmatchedLength, r)
+ }
+ }
+ return false
+ })
+ tree.WalkPath(key, fn)
+
+ if len(validation.Matched) != 0 {
+ validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_VALID
+ validation.Reason = RPKI_VALIDATION_REASON_TYPE_NONE
+ } else if len(validation.UnmatchedAs) != 0 {
+ validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
+ validation.Reason = RPKI_VALIDATION_REASON_TYPE_AS
+ } else if len(validation.UnmatchedLength) != 0 {
+ validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
+ validation.Reason = RPKI_VALIDATION_REASON_TYPE_LENGTH
+ } else {
+ validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND
+ validation.Reason = RPKI_VALIDATION_REASON_TYPE_NONE
+ }
+
+ return validation
+}
+
+func (rt *ROATable) Validate(path *Path) *Validation {
+ if path.IsWithdraw || path.IsEOR() {
+ // RPKI isn't enabled or invalid path
+ return nil
+ }
+ if tree, ok := rt.Roas[path.GetRouteFamily()]; ok {
+ return validatePath(path.OriginInfo().source.LocalAS, tree, path.GetNlri().String(), path.GetAsPath())
+ }
+ return nil
+}
+
+func (rt *ROATable) Info(family bgp.RouteFamily) (map[string]uint32, map[string]uint32) {
+ records := make(map[string]uint32)
+ prefixes := make(map[string]uint32)
+
+ tree := rt.Roas[family]
+ tree.Walk(func(s string, v interface{}) bool {
+ b, _ := v.(*roaBucket)
+ tmpRecords := make(map[string]uint32)
+ for _, roa := range b.entries {
+ tmpRecords[roa.Src]++
+ }
+
+ for src, r := range tmpRecords {
+ if r > 0 {
+ records[src] += r
+ prefixes[src]++
+ }
+ }
+ return false
+ })
+ return records, prefixes
+}
+
+func (rt *ROATable) List(family bgp.RouteFamily) ([]*ROA, error) {
+ var rfList []bgp.RouteFamily
+ switch family {
+ case bgp.RF_IPv4_UC:
+ rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC}
+ case bgp.RF_IPv6_UC:
+ rfList = []bgp.RouteFamily{bgp.RF_IPv6_UC}
+ default:
+ rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC}
+ }
+ l := make([]*ROA, 0)
+ for _, rf := range rfList {
+ if tree, ok := rt.Roas[rf]; ok {
+ tree.Walk(func(s string, v interface{}) bool {
+ b, _ := v.(*roaBucket)
+ var roaList roas
+ for _, r := range b.entries {
+ roaList = append(roaList, r)
+ }
+ sort.Sort(roaList)
+ for _, roa := range roaList {
+ l = append(l, roa)
+ }
+ return false
+ })
+ }
+ }
+ return l, nil
+}
+
+type roas []*ROA
+
+func (r roas) Len() int {
+ return len(r)
+}
+
+func (r roas) Swap(i, j int) {
+ r[i], r[j] = r[j], r[i]
+}
+
+func (r roas) Less(i, j int) bool {
+ r1 := r[i]
+ r2 := r[j]
+
+ if r1.MaxLen < r2.MaxLen {
+ return true
+ } else if r1.MaxLen > r2.MaxLen {
+ return false
+ }
+
+ if r1.AS < r2.AS {
+ return true
+ }
+ return false
+}
diff --git a/pkg/server/rpki_test.go b/internal/pkg/table/roa_test.go
index 9f903a77..6b98269e 100644
--- a/pkg/server/rpki_test.go
+++ b/internal/pkg/table/roa_test.go
@@ -1,19 +1,4 @@
-// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package server
+package table
import (
"net"
@@ -21,11 +6,9 @@ import (
"strings"
"testing"
+ radix "github.com/armon/go-radix"
"github.com/osrg/gobgp/internal/pkg/config"
- "github.com/osrg/gobgp/internal/pkg/table"
"github.com/osrg/gobgp/pkg/packet/bgp"
-
- radix "github.com/armon/go-radix"
"github.com/stretchr/testify/assert"
)
@@ -63,13 +46,13 @@ func validateOne(tree *radix.Tree, cidr, aspathStr string) config.RpkiValidation
func TestValidate0(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("192.168.0.0").To4(), 24, 32, 100, ""))
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("192.168.0.0").To4(), 24, 24, 200, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("192.168.0.0").To4(), 24, 32, 100, ""))
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("192.168.0.0").To4(), 24, 24, 200, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "192.168.0.0/24", "100")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID)
@@ -92,12 +75,12 @@ func TestValidate0(t *testing.T) {
func TestValidate1(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 16, 65000, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 16, 65000, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/16", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID)
@@ -108,11 +91,11 @@ func TestValidate1(t *testing.T) {
func TestValidate2(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
+ table := NewROATable()
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/16", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND)
@@ -123,22 +106,22 @@ func TestValidate2(t *testing.T) {
func TestValidate3(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 16, 65000, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 16, 65000, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/8", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND)
r = validateOne(tree, "10.0.0.0/17", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_INVALID)
- manager, _ = newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65000, ""))
+ table = NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65000, ""))
- tree = manager.Roas[bgp.RF_IPv4_UC]
+ tree = table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/17", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID)
}
@@ -146,12 +129,12 @@ func TestValidate3(t *testing.T) {
func TestValidate4(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 16, 65000, ""))
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 16, 65001, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 16, 65000, ""))
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 16, 65001, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/16", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID)
@@ -162,12 +145,12 @@ func TestValidate4(t *testing.T) {
func TestValidate5(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 17, 17, 65000, ""))
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.128.0").To4(), 17, 17, 65000, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 17, 17, 65000, ""))
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.128.0").To4(), 17, 17, 65000, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/16", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND)
}
@@ -175,11 +158,11 @@ func TestValidate5(t *testing.T) {
func TestValidate6(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 8, 32, 0, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 8, 32, 0, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/7", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND)
@@ -193,11 +176,11 @@ func TestValidate6(t *testing.T) {
func TestValidate7(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65000, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65000, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/24", "{65000}")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND)
@@ -211,12 +194,12 @@ func TestValidate7(t *testing.T) {
func TestValidate8(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 0, ""))
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65000, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 0, ""))
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65000, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/24", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID)
@@ -227,12 +210,12 @@ func TestValidate8(t *testing.T) {
func TestValidate9(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 24, 24, 65000, ""))
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65001, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 24, 24, 65000, ""))
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65001, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/24", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID)
@@ -243,12 +226,12 @@ func TestValidate9(t *testing.T) {
func TestValidate10(t *testing.T) {
assert := assert.New(t)
- manager, _ := newROAManager(0)
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 24, 24, 0, ""))
- manager.addROA(table.NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65001, ""))
+ table := NewROATable()
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 24, 24, 0, ""))
+ table.Add(NewROA(bgp.AFI_IP, net.ParseIP("10.0.0.0").To4(), 16, 24, 65001, ""))
var r config.RpkiValidationResultType
- tree := manager.Roas[bgp.RF_IPv4_UC]
+ tree := table.Roas[bgp.RF_IPv4_UC]
r = validateOne(tree, "10.0.0.0/24", "65000")
assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_INVALID)
diff --git a/pkg/server/rpki.go b/pkg/server/rpki.go
index c46f8ffd..9eb3d2b7 100644
--- a/pkg/server/rpki.go
+++ b/pkg/server/rpki.go
@@ -20,7 +20,6 @@ import (
"fmt"
"io"
"net"
- "sort"
"strconv"
"time"
@@ -29,7 +28,6 @@ import (
"github.com/osrg/gobgp/pkg/packet/bgp"
"github.com/osrg/gobgp/pkg/packet/rtr"
- "github.com/armon/go-radix"
log "github.com/sirupsen/logrus"
"golang.org/x/net/context"
)
@@ -42,41 +40,6 @@ func before(a, b uint32) bool {
return int32(a-b) < 0
}
-type roaBucket struct {
- Prefix *table.IPPrefix
- entries []*table.ROA
-}
-
-func (r *roaBucket) GetEntries() []*table.ROA {
- return r.entries
-}
-
-type roas []*table.ROA
-
-func (r roas) Len() int {
- return len(r)
-}
-
-func (r roas) Swap(i, j int) {
- r[i], r[j] = r[j], r[i]
-}
-
-func (r roas) Less(i, j int) bool {
- r1 := r[i]
- r2 := r[j]
-
- if r1.MaxLen < r2.MaxLen {
- return true
- } else if r1.MaxLen > r2.MaxLen {
- return false
- }
-
- if r1.AS < r2.AS {
- return true
- }
- return false
-}
-
type roaEventType uint8
const (
@@ -94,36 +57,24 @@ type roaEvent struct {
}
type roaManager struct {
- AS uint32
- Roas map[bgp.RouteFamily]*radix.Tree
eventCh chan *roaEvent
clientMap map[string]*roaClient
+ table *table.ROATable
}
-func newROAManager(as uint32) (*roaManager, error) {
+func newROAManager(table *table.ROATable) *roaManager {
m := &roaManager{
- AS: as,
- Roas: make(map[bgp.RouteFamily]*radix.Tree),
+ table: table,
}
- m.Roas[bgp.RF_IPv4_UC] = radix.New()
- m.Roas[bgp.RF_IPv6_UC] = radix.New()
m.eventCh = make(chan *roaEvent)
m.clientMap = make(map[string]*roaClient)
- return m, nil
+ return m
}
func (m *roaManager) enabled() bool {
return len(m.clientMap) != 0
}
-func (m *roaManager) SetAS(as uint32) error {
- if m.AS != 0 {
- return fmt.Errorf("AS was already configured")
- }
- m.AS = as
- return nil
-}
-
func (m *roaManager) AddServer(host string, lifetime int64) error {
address, port, err := net.SplitHostPort(host)
if err != nil {
@@ -145,35 +96,11 @@ func (m *roaManager) DeleteServer(host string) error {
return fmt.Errorf("ROA server doesn't exists %s", host)
}
client.stop()
- m.deleteAllROA(host)
+ m.table.DeleteAll(host)
delete(m.clientMap, host)
return nil
}
-func (m *roaManager) deleteAllROA(network string) {
- for _, tree := range m.Roas {
- deleteKeys := make([]string, 0, tree.Len())
- tree.Walk(func(s string, v interface{}) bool {
- b, _ := v.(*roaBucket)
- newEntries := make([]*table.ROA, 0, len(b.entries))
- for _, r := range b.entries {
- if r.Src != network {
- newEntries = append(newEntries, r)
- }
- }
- if len(newEntries) > 0 {
- b.entries = newEntries
- } else {
- deleteKeys = append(deleteKeys, s)
- }
- return false
- })
- for _, key := range deleteKeys {
- tree.Delete(key)
- }
- }
-}
-
func (m *roaManager) Enable(address string) error {
for network, client := range m.clientMap {
add, _, _ := net.SplitHostPort(network)
@@ -190,7 +117,7 @@ func (m *roaManager) Disable(address string) error {
add, _, _ := net.SplitHostPort(network)
if add == address {
client.reset()
- m.deleteAllROA(add)
+ m.table.DeleteAll(add)
return nil
}
}
@@ -206,7 +133,7 @@ func (m *roaManager) SoftReset(address string) error {
add, _, _ := net.SplitHostPort(network)
if add == address {
client.softReset()
- m.deleteAllROA(network)
+ m.table.DeleteAll(network)
return nil
}
}
@@ -264,77 +191,11 @@ func (m *roaManager) HandleROAEvent(ev *roaEvent) {
log.WithFields(log.Fields{"Topic": "rpki"}).Infof("Reconnected to %s. Ignore timeout", client.host)
} else {
log.WithFields(log.Fields{"Topic": "rpki"}).Infof("Deleting all ROAs due to timeout with:%s", client.host)
- m.deleteAllROA(client.host)
+ m.table.DeleteAll(client.host)
}
}
}
-func (m *roaManager) roa2tree(roa *table.ROA) (*radix.Tree, string) {
- tree := m.Roas[bgp.RF_IPv4_UC]
- if roa.Family == bgp.AFI_IP6 {
- tree = m.Roas[bgp.RF_IPv6_UC]
- }
- return tree, table.IpToRadixkey(roa.Prefix.Prefix, roa.Prefix.Length)
-}
-
-func (m *roaManager) deleteROA(roa *table.ROA) {
- tree, key := m.roa2tree(roa)
- b, _ := tree.Get(key)
- if b != nil {
- bucket := b.(*roaBucket)
- newEntries := make([]*table.ROA, 0, len(bucket.entries))
- for _, r := range bucket.entries {
- if !r.Equal(roa) {
- newEntries = append(newEntries, r)
- }
- }
- if len(newEntries) != len(bucket.entries) {
- bucket.entries = newEntries
- if len(newEntries) == 0 {
- tree.Delete(key)
- }
- return
- }
- }
- log.WithFields(log.Fields{
- "Topic": "rpki",
- "Prefix": roa.Prefix.Prefix.String(),
- "Prefix Length": roa.Prefix.Length,
- "AS": roa.AS,
- "Max Length": roa.MaxLen,
- }).Info("Can't withdraw a ROA")
-}
-
-func (m *roaManager) DeleteROA(roa *table.ROA) {
- m.deleteROA(roa)
-}
-
-func (m *roaManager) addROA(roa *table.ROA) {
- tree, key := m.roa2tree(roa)
- b, _ := tree.Get(key)
- var bucket *roaBucket
- if b == nil {
- bucket = &roaBucket{
- Prefix: roa.Prefix,
- entries: make([]*table.ROA, 0),
- }
- tree.Insert(key, bucket)
- } else {
- bucket = b.(*roaBucket)
- for _, r := range bucket.entries {
- if r.Equal(roa) {
- // we already have the same one
- return
- }
- }
- }
- bucket.entries = append(bucket.entries, roa)
-}
-
-func (m *roaManager) AddROA(roa *table.ROA) {
- m.addROA(roa)
-}
-
func (m *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerState, buf []byte) {
received := &state.RpkiMessages.RpkiReceived
@@ -367,19 +228,19 @@ func (m *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerSta
roa := table.NewROA(family, msg.Prefix, msg.PrefixLen, msg.MaxLen, msg.AS, client.host)
if (msg.Flags & 1) == 1 {
if client.endOfData {
- m.addROA(roa)
+ m.table.Add(roa)
} else {
client.pendingROAs = append(client.pendingROAs, roa)
}
} else {
- m.deleteROA(roa)
+ m.table.Delete(roa)
}
case *rtr.RTREndOfData:
received.EndOfData++
if client.sessionID != msg.RTRCommon.SessionID {
// remove all ROAs related with the
// previous session
- m.deleteAllROA(client.host)
+ m.table.DeleteAll(client.host)
}
client.sessionID = msg.RTRCommon.SessionID
client.serialNumber = msg.RTRCommon.SerialNumber
@@ -389,7 +250,7 @@ func (m *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerSta
client.timer = nil
}
for _, roa := range client.pendingROAs {
- m.addROA(roa)
+ m.table.Add(roa)
}
client.pendingROAs = make([]*table.ROA, 0)
case *rtr.RTRCacheReset:
@@ -408,30 +269,8 @@ func (m *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerSta
}
func (m *roaManager) GetServers() []*config.RpkiServer {
- f := func(tree *radix.Tree) (map[string]uint32, map[string]uint32) {
- records := make(map[string]uint32)
- prefixes := make(map[string]uint32)
-
- tree.Walk(func(s string, v interface{}) bool {
- b, _ := v.(*roaBucket)
- tmpRecords := make(map[string]uint32)
- for _, roa := range b.entries {
- tmpRecords[roa.Src]++
- }
-
- for src, r := range tmpRecords {
- if r > 0 {
- records[src] += r
- prefixes[src]++
- }
- }
- return false
- })
- return records, prefixes
- }
-
- recordsV4, prefixesV4 := f(m.Roas[bgp.RF_IPv4_UC])
- recordsV6, prefixesV6 := f(m.Roas[bgp.RF_IPv6_UC])
+ recordsV4, prefixesV4 := m.table.Info(bgp.RF_IPv4_UC)
+ recordsV6, prefixesV6 := m.table.Info(bgp.RF_IPv6_UC)
l := make([]*config.RpkiServer, 0, len(m.clientMap))
for _, client := range m.clientMap {
@@ -468,123 +307,6 @@ func (m *roaManager) GetServers() []*config.RpkiServer {
return l
}
-func (m *roaManager) GetRoa(family bgp.RouteFamily) ([]*table.ROA, error) {
- if len(m.clientMap) == 0 {
- return []*table.ROA{}, fmt.Errorf("RPKI server isn't configured")
- }
- var rfList []bgp.RouteFamily
- switch family {
- case bgp.RF_IPv4_UC:
- rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC}
- case bgp.RF_IPv6_UC:
- rfList = []bgp.RouteFamily{bgp.RF_IPv6_UC}
- default:
- rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC}
- }
- l := make([]*table.ROA, 0)
- for _, rf := range rfList {
- if tree, ok := m.Roas[rf]; ok {
- tree.Walk(func(s string, v interface{}) bool {
- b, _ := v.(*roaBucket)
- var roaList roas
- for _, r := range b.entries {
- roaList = append(roaList, r)
- }
- sort.Sort(roaList)
- for _, roa := range roaList {
- l = append(l, roa)
- }
- return false
- })
- }
- }
- return l, nil
-}
-
-func validatePath(ownAs uint32, tree *radix.Tree, cidr string, asPath *bgp.PathAttributeAsPath) *table.Validation {
- var as uint32
-
- validation := &table.Validation{
- Status: config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND,
- Reason: table.RPKI_VALIDATION_REASON_TYPE_NONE,
- Matched: make([]*table.ROA, 0),
- UnmatchedLength: make([]*table.ROA, 0),
- UnmatchedAs: make([]*table.ROA, 0),
- }
-
- if asPath == nil || len(asPath.Value) == 0 {
- as = ownAs
- } else {
- param := asPath.Value[len(asPath.Value)-1]
- switch param.GetType() {
- case bgp.BGP_ASPATH_ATTR_TYPE_SEQ:
- asList := param.GetAS()
- if len(asList) == 0 {
- as = ownAs
- } else {
- as = asList[len(asList)-1]
- }
- case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
- as = ownAs
- default:
- return validation
- }
- }
- _, n, _ := net.ParseCIDR(cidr)
- ones, _ := n.Mask.Size()
- prefixLen := uint8(ones)
- key := table.IpToRadixkey(n.IP, prefixLen)
- _, b, _ := tree.LongestPrefix(key)
- if b == nil {
- return validation
- }
-
- var bucket *roaBucket
- fn := radix.WalkFn(func(k string, v interface{}) bool {
- bucket, _ = v.(*roaBucket)
- for _, r := range bucket.entries {
- if prefixLen <= r.MaxLen {
- if r.AS != 0 && r.AS == as {
- validation.Matched = append(validation.Matched, r)
- } else {
- validation.UnmatchedAs = append(validation.UnmatchedAs, r)
- }
- } else {
- validation.UnmatchedLength = append(validation.UnmatchedLength, r)
- }
- }
- return false
- })
- tree.WalkPath(key, fn)
-
- if len(validation.Matched) != 0 {
- validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_VALID
- validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_NONE
- } else if len(validation.UnmatchedAs) != 0 {
- validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
- validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_AS
- } else if len(validation.UnmatchedLength) != 0 {
- validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
- validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_LENGTH
- } else {
- validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND
- validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_NONE
- }
-
- return validation
-}
-
-func (m *roaManager) validate(path *table.Path) *table.Validation {
- if len(m.clientMap) == 0 || path.IsWithdraw || path.IsEOR() {
- // RPKI isn't enabled or invalid path
- return nil
- }
- if tree, ok := m.Roas[path.GetRouteFamily()]; ok {
- return validatePath(m.AS, tree, path.GetNlri().String(), path.GetAsPath())
- }
- return nil
-}
-
type roaClient struct {
host string
conn *net.TCPConn
diff --git a/pkg/server/server.go b/pkg/server/server.go
index 966f48b7..4ee64cf6 100644
--- a/pkg/server/server.go
+++ b/pkg/server/server.go
@@ -134,6 +134,7 @@ type BgpServer struct {
zclient *zebraClient
bmpManager *bmpClientManager
mrtManager *mrtManager
+ roaTable *table.ROATable
uuidMap map[string]uuid.UUID
}
@@ -142,16 +143,16 @@ func NewBgpServer(opt ...ServerOption) *BgpServer {
for _, o := range opt {
o(&opts)
}
-
- roaManager, _ := newROAManager(0)
+ roaTable := table.NewROATable()
s := &BgpServer{
neighborMap: make(map[string]*peer),
peerGroupMap: make(map[string]*peerGroup),
policy: table.NewRoutingPolicy(),
- roaManager: roaManager,
mgmtCh: make(chan *mgmtOp, 1),
watcherMap: make(map[watchEventType][]*watcher),
uuidMap: make(map[string]uuid.UUID),
+ roaManager: newROAManager(roaTable),
+ roaTable: roaTable,
}
s.bmpManager = newBmpClientManager(s)
s.mrtManager = newMrtManager(s)
@@ -674,7 +675,7 @@ func (s *BgpServer) filterpath(peer *peer, path, old *table.Path) *table.Path {
if stop {
return path
}
- options.Validate = s.roaManager.validate
+ options.Validate = s.roaTable.Validate
path = peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, path, options)
// When 'path' is filtered (path == nil), check 'old' has been sent to this peer.
// If it has, send withdrawal to the peer.
@@ -994,7 +995,7 @@ func (s *BgpServer) sendSecondaryRoutes(peer *peer, newPath *table.Path, dsts []
if stop {
return nil
}
- options.Validate = s.roaManager.validate
+ options.Validate = s.roaTable.Validate
path = peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, path, options)
if path != nil {
return s.postFilterpath(peer, path)
@@ -1109,7 +1110,7 @@ func (s *BgpServer) propagateUpdate(peer *peer, pathList []*table.Path) {
}
policyOptions := &table.PolicyOptions{
- Validate: s.roaManager.validate,
+ Validate: s.roaTable.Validate,
}
if !rs && peer != nil {
@@ -2117,8 +2118,6 @@ func (s *BgpServer) StartBgp(ctx context.Context, r *api.StartBgpRequest) error
// update route selection options
table.SelectionOptions = c.RouteSelectionOptions.Config
table.UseMultiplePaths = c.UseMultiplePaths.Config
-
- s.roaManager.SetAS(s.bgpConfig.Global.Config.As)
return nil
}, false)
}
@@ -2383,7 +2382,7 @@ func (s *BgpServer) validateTable(r *table.Table) (v []*table.Validation) {
v = make([]*table.Validation, 0, len(r.GetDestinations()))
for _, d := range r.GetDestinations() {
for _, p := range d.GetAllKnownPathList() {
- v = append(v, s.roaManager.validate(p))
+ v = append(v, s.roaTable.Validate(p))
}
}
}
@@ -2465,7 +2464,7 @@ func (s *BgpServer) getAdjRib(addr string, family bgp.RouteFamily, in bool, enab
if enableFiltered {
for _, path := range peer.adjRibIn.PathList([]bgp.RouteFamily{family}, true) {
options := &table.PolicyOptions{
- Validate: s.roaManager.validate,
+ Validate: s.roaTable.Validate,
}
if s.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_IMPORT, path, options) == nil {
filtered[path.GetNlri().String()] = path
@@ -2480,7 +2479,7 @@ func (s *BgpServer) getAdjRib(addr string, family bgp.RouteFamily, in bool, enab
if stop {
continue
}
- options.Validate = s.roaManager.validate
+ options.Validate = s.roaTable.Validate
p := peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, path, options)
if p == nil {
filtered[path.GetNlri().String()] = path
@@ -3615,7 +3614,7 @@ func (s *BgpServer) ListRpkiTable(ctx context.Context, r *api.ListRpkiTableReque
if r.Family != nil {
family = bgp.AfiSafiToRouteFamily(uint16(r.Family.Afi), uint8(r.Family.Safi))
}
- roas, err := s.roaManager.GetRoa(family)
+ roas, err := s.roaTable.List(family)
if err == nil {
l = append(l, newRoaListFromTableStructList(roas)...)
}