summaryrefslogtreecommitdiffhomepage
path: root/pkg/server/rpki.go
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@gmail.com>2019-09-08 18:45:27 +0900
committerFUJITA Tomonori <fujita.tomonori@gmail.com>2019-10-22 21:17:05 +0900
commita1a523a1b3323685e97cb88691fcd76c39156195 (patch)
treef62fb6e8e50b985f16597d8e4e2f7e0ebabe40f7 /pkg/server/rpki.go
parentf1f0f77f5989f113336246a96737b7f246485ee1 (diff)
move roa table code to table/ from server/
As the name implies, table/ is more appropriate for roa table code. Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Diffstat (limited to 'pkg/server/rpki.go')
-rw-r--r--pkg/server/rpki.go306
1 files changed, 14 insertions, 292 deletions
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