Skip to content

Commit

Permalink
Implement draft-spaghetti-sidrops-aspa-slurm-0
Browse files Browse the repository at this point in the history
  • Loading branch information
benjojo committed Feb 23, 2023
1 parent 643bccf commit 1e32148
Show file tree
Hide file tree
Showing 3 changed files with 324 additions and 25 deletions.
43 changes: 31 additions & 12 deletions cmd/stayrtr/stayrtr.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,17 @@ func (s *state) updateFromNewState() error {
if vrpsjson == nil {
return nil
}
bgpsecjson := s.lastdata.BgpSecKeys
if bgpsecjson == nil {
bgpsecjson = make([]prefixfile.BgpSecKeyJson, 0)
}
aspajson := s.lastdata.ASPA
if aspajson == nil {
aspajson = &prefixfile.ProviderAuthorizationsJson{
IPv4: make([]prefixfile.ASPAJson, 0),
IPv6: make([]prefixfile.ASPAJson, 0),
}
}

buildtime, err := time.Parse(time.RFC3339, s.lastdata.Metadata.Buildtime)
if s.lastdata.Metadata.GeneratedUnix != nil {
Expand All @@ -348,16 +359,13 @@ func (s *state) updateFromNewState() error {
}

if s.slurm != nil {
kept, removed := s.slurm.FilterOnVRPs(vrpsjson)
asserted := s.slurm.AssertVRPs()
log.Infof("Slurm filtering: %v kept, %v removed, %v asserted", len(kept), len(removed), len(asserted))
vrpsjson = append(kept, asserted...)
vrpsjson, aspajson.IPv4, aspajson.IPv6, bgpsecjson = s.slurm.FilterAssert(vrpsjson, aspajson.IPv4, aspajson.IPv6, bgpsecjson, log.StandardLogger())
}

vrps, brks, vaps, count, countv4, countv6 := processData(vrpsjson, s.lastdata.BgpSecKeys, s.lastdata.ASPA)
vrps, brks, vaps, count, countv4, countv6 := processData(vrpsjson, bgpsecjson, aspajson)

log.Infof("New update (%v uniques, %v total prefixes).", len(vrps), count)
return s.applyUpdateFromNewState(vrps, brks, vaps, sessid, vrpsjson, s.lastdata.BgpSecKeys, s.lastdata.ASPA, countv4, countv6)
return s.applyUpdateFromNewState(vrps, brks, vaps, sessid, vrpsjson, bgpsecjson, aspajson, countv4, countv6)
}

// Update the state based on the currently loaded files
Expand All @@ -368,8 +376,22 @@ func (s *state) reloadFromCurrentState() error {
if vrpsjson == nil {
return nil
}
bgpsecjson := s.lastdata.BgpSecKeys
if bgpsecjson == nil {
bgpsecjson = make([]prefixfile.BgpSecKeyJson, 0)
}
aspajson := s.lastdata.ASPA
if aspajson == nil {
aspajson = &prefixfile.ProviderAuthorizationsJson{
IPv4: make([]prefixfile.ASPAJson, 0),
IPv6: make([]prefixfile.ASPAJson, 0),
}
}

buildtime, err := time.Parse(time.RFC3339, s.lastdata.Metadata.Buildtime)
if s.lastdata.Metadata.GeneratedUnix != nil {
buildtime, err = time.Unix(int64(*s.lastdata.Metadata.GeneratedUnix), 0), nil
}
if s.checktime {
if err != nil {
return err
Expand All @@ -382,16 +404,13 @@ func (s *state) reloadFromCurrentState() error {
}

if s.slurm != nil {
kept, removed := s.slurm.FilterOnVRPs(vrpsjson)
asserted := s.slurm.AssertVRPs()
log.Infof("Slurm filtering: %v kept, %v removed, %v asserted", len(kept), len(removed), len(asserted))
vrpsjson = append(kept, asserted...)
vrpsjson, aspajson.IPv4, aspajson.IPv6, bgpsecjson = s.slurm.FilterAssert(vrpsjson, aspajson.IPv4, aspajson.IPv6, bgpsecjson, log.StandardLogger())
}

vrps, brks, vaps, count, countv4, countv6 := processData(vrpsjson, s.lastdata.BgpSecKeys, s.lastdata.ASPA)
vrps, brks, vaps, count, countv4, countv6 := processData(vrpsjson, bgpsecjson, aspajson)
if s.server.CountVRPs() != count {
log.Infof("New update to old state (%v uniques, %v total prefixes). (old %v - new %v)", len(vrps), count, s.server.CountVRPs(), count)
return s.applyUpdateFromNewState(vrps, brks, vaps, sessid, vrpsjson, s.lastdata.BgpSecKeys, s.lastdata.ASPA, countv4, countv6)
return s.applyUpdateFromNewState(vrps, brks, vaps, sessid, vrpsjson, bgpsecjson, aspajson, countv4, countv6)
}
return nil
}
Expand Down
189 changes: 176 additions & 13 deletions prefixfile/slurm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
package prefixfile

import (
"bytes"
"encoding/hex"
"encoding/json"
"io"
"net"
"strings"
)

type SlurmPrefixFilter struct {
Expand All @@ -15,8 +18,9 @@ type SlurmPrefixFilter struct {
}

type SlurmBGPsecFilter struct {
ASN uint32 `json:"asn"`
Comment string `json:"comment"`
ASN *uint32 `json:"asn,omitempty"`
SKI []byte `json:"SKI,omitempty"`
Comment string `json:"comment"`
}

type SlurmASPAFilter struct {
Expand Down Expand Up @@ -101,9 +105,9 @@ func DecodeJSONSlurm(buf io.Reader) (*SlurmConfig, error) {
return slurm, nil
}

func (s *SlurmValidationOutputFilters) FilterOnVRPs(vrps []VRPJson) ([]VRPJson, []VRPJson) {
added := make([]VRPJson, 0)
removed := make([]VRPJson, 0)
func (s *SlurmValidationOutputFilters) FilterOnVRPs(vrps []VRPJson) (added, removed []VRPJson) {
added = make([]VRPJson, 0)
removed = make([]VRPJson, 0)
if s.PrefixFilters == nil || len(s.PrefixFilters) == 0 {
return vrps, removed
}
Expand Down Expand Up @@ -146,8 +150,92 @@ func (s *SlurmValidationOutputFilters) FilterOnVRPs(vrps []VRPJson) ([]VRPJson,
return added, removed
}

func (s *SlurmConfig) FilterOnVRPs(vrps []VRPJson) ([]VRPJson, []VRPJson) {
return s.ValidationOutputFilters.FilterOnVRPs(vrps)
func (s *SlurmValidationOutputFilters) FilterOnBRKs(brks []BgpSecKeyJson) (added, removed []BgpSecKeyJson) {
added = make([]BgpSecKeyJson, 0)
removed = make([]BgpSecKeyJson, 0)
if s.BgpsecFilters == nil || len(s.BgpsecFilters) == 0 {
return brks, removed
}
for _, brk := range brks {
var skiCache []byte
var wasRemoved bool
for _, filter := range s.BgpsecFilters {
if filter.ASN != nil {
if brk.Asn == *filter.ASN {
if len(filter.SKI) != 0 {
// We need to compare the SKIs then
if skiCache == nil { // We have not yet decoded the ski hex
var err error
skiCache, err = hex.DecodeString(brk.Ski)
if err != nil {
// Ski could not be decoded, so we can't filter
continue
}
}
if bytes.Equal(filter.SKI, skiCache) {
removed = append(removed, brk)
wasRemoved = true
break
}
} else {
// Only a ASN match was needed
removed = append(removed, brk)
wasRemoved = true
break
}
}
}

if len(filter.SKI) != 0 && filter.ASN == nil {
// We need to compare just the SKIs then
if skiCache == nil { // We have not yet decoded the ski hex
var err error
skiCache, err = hex.DecodeString(brk.Ski)
if err != nil {
// Ski could not be decoded, so we can't filter
continue
}
}
if bytes.Equal(filter.SKI, skiCache) {
removed = append(removed, brk)
wasRemoved = true
break
}
}
}

if !wasRemoved {
added = append(added, brk)
}
}
return added, removed
}

func (s *SlurmValidationOutputFilters) FilterOnVAPs(vaps []ASPAJson, ipv6 bool) (added, removed []ASPAJson) {
added = make([]ASPAJson, 0)
removed = make([]ASPAJson, 0)
if s.AspaFilters == nil || len(s.AspaFilters) == 0 {
return vaps, removed
}
for _, vap := range vaps {
var wasRemoved bool
for _, filter := range s.AspaFilters {
if strings.Contains(filter.Afi, "6") && !ipv6 {
continue
}

if vap.CustomerAsid == filter.CustomerASid {
removed = append(removed, vap)
wasRemoved = true
break
}
}

if !wasRemoved {
added = append(added, vap)
}
}
return added, removed
}

func (s *SlurmLocallyAddedAssertions) AssertVRPs() []VRPJson {
Expand Down Expand Up @@ -175,12 +263,87 @@ func (s *SlurmLocallyAddedAssertions) AssertVRPs() []VRPJson {
return vrps
}

func (s *SlurmConfig) AssertVRPs() []VRPJson {
return s.LocallyAddedAssertions.AssertVRPs()
func (s *SlurmLocallyAddedAssertions) AssertVAPs() (v4, v6 []ASPAJson) {
vapsv4, vapsv6 := make([]ASPAJson, 0), make([]ASPAJson, 0)

if s.AspaAssertions == nil || len(s.AspaAssertions) == 0 {
return vapsv4, vapsv6
}
for _, assertion := range s.AspaAssertions {
vap := ASPAJson{
CustomerAsid: assertion.CustomerASNid,
Providers: assertion.ProviderSet,
}
if strings.Contains(assertion.Afi, "6") {
vapsv6 = append(vapsv6, vap)
} else {
vapsv4 = append(vapsv4, vap)
}
}
return vapsv4, vapsv6
}

func (s *SlurmLocallyAddedAssertions) AssertBRKs() []BgpSecKeyJson {
brks := make([]BgpSecKeyJson, 0)

if s.BgpsecAssertions == nil || len(s.BgpsecAssertions) == 0 {
return brks
}
for _, assertion := range s.BgpsecAssertions {
hexSki := hex.EncodeToString(assertion.SKI)
brk := BgpSecKeyJson{
Asn: assertion.ASN,
Pubkey: assertion.RouterPublicKey,
Ski: hexSki,
}
brks = append(brks, brk)
}
return brks
}

func (s *SlurmConfig) GetAssertions() (vrps []VRPJson, VAPv4, VAPv6 []ASPAJson, BRKs []BgpSecKeyJson) {
vrps = s.LocallyAddedAssertions.AssertVRPs()
VAPv4, VAPv6 = s.LocallyAddedAssertions.AssertVAPs()
BRKs = s.LocallyAddedAssertions.AssertBRKs()
return
}

func (s *SlurmConfig) FilterAssert(vrps []VRPJson, VAPv4, VAPv6 []ASPAJson, BRKs []BgpSecKeyJson, log Logger) (
ovrps []VRPJson, oVAPv4, oVAPv6 []ASPAJson, oBRKs []BgpSecKeyJson) {
//
filteredVRPs, removedVRPs := s.ValidationOutputFilters.FilterOnVRPs(vrps)
filteredVAP4s, removedVAP4s := s.ValidationOutputFilters.FilterOnVAPs(VAPv4, false)
filteredVAP6s, removedVAP6s := s.ValidationOutputFilters.FilterOnVAPs(VAPv6, true)
filteredBRKs, removedBRKs := s.ValidationOutputFilters.FilterOnBRKs(BRKs)

assertVRPs, assertVAP4, assertVAP6, assertBRKs := s.GetAssertions()

ovrps = append(filteredVRPs, assertVRPs...)
oVAPv4 = append(filteredVAP4s, assertVAP4...)
oVAPv6 = append(filteredVAP6s, assertVAP6...)
oBRKs = append(filteredBRKs, assertBRKs...)

if log != nil {
if len(s.ValidationOutputFilters.PrefixFilters) != 0 {
log.Infof("Slurm VRP filtering: %v kept, %v removed, %v asserted", len(filteredVRPs), len(removedVRPs), len(ovrps))
}

if len(s.ValidationOutputFilters.BgpsecFilters) != 0 {
log.Infof("Slurm Router Key filtering: %v kept, %v removed, %v asserted", len(filteredBRKs), len(removedBRKs), len(oBRKs))
}

if len(s.ValidationOutputFilters.AspaFilters) != 0 {
log.Infof("Slurm ASPA v4 filtering: %v kept, %v removed, %v asserted", len(filteredVAP4s), len(removedVAP4s), len(oVAPv4))
log.Infof("Slurm ASPA v6 filtering: %v kept, %v removed, %v asserted", len(filteredVAP6s), len(removedVAP6s), len(oVAPv6))
}
}
return
}

func (s *SlurmConfig) FilterAssert(vrps []VRPJson) []VRPJson {
a, _ := s.FilterOnVRPs(vrps)
b := s.AssertVRPs()
return append(a, b...)
type Logger interface {
Debugf(string, ...interface{})
Printf(string, ...interface{})
Warnf(string, ...interface{})
Errorf(string, ...interface{})
Infof(string, ...interface{})
}
Loading

0 comments on commit 1e32148

Please sign in to comment.