1
0
mirror of https://github.com/bgp/stayrtr.git synced 2024-05-06 15:54:54 +00:00

Implement draft-ietf-sidrops-8210bis-10 ROA PDU Race Minimization

It will now sort entries before they go out, Sorted by:

Largest CIDR > Largest Max Length > IP address
This commit is contained in:
Ben Cartwright-Cox
2023-02-22 17:36:06 +00:00
parent 187410d9b6
commit e98648f8b2

View File

@ -8,6 +8,7 @@ import (
"io"
"math/rand"
"net"
"sort"
"sync"
"time"
@ -1020,6 +1021,45 @@ func (ASPAr *ASPARecord) GetFlag() uint8 {
}
func (c *Client) SendSDs(sessionId uint16, serialNumber uint32, data []SendableData) {
sort.Slice(data, func(i, j int) bool {
if data[i].Type() == "VRP" && data[i].Type() != "VRP" {
return false // Always send VRPs first
}
if data[i].Type() == "VRP" && data[j].Type() == "VRP" {
// Sort VRPs as per draft-ietf-sidrops-8210bis-10
/*
11. ROA PDU Race Minimization
When a cache is sending ROA (IPv4 or IPv6) PDUs to a router, especially an initial
full load in response to a Reset Query PDU, two undesirable race conditions are possible:
Break Before Make:
For some prefix P, an AS may announce two (or more) ROAs because they are in the
process of changing what provider AS is announcing P. This is a case of "make before break."
If a cache is feeding a router and sends the one not yet in service a significant time
before sending the one currently in service, then BGP data could be marked invalid during
the interval. To minimize that interval, the cache SHOULD announce all ROAs for the same
prefix as close to sequentially as possible.
Shorter Prefix First:
If an AS has issued a ROA for P0, and another AS (likely their customer) has issued a ROA
for P1 which is a sub-prefix of P0, a router which receives the ROA for P0 before that for
P1 is likely to mark a BGP prefix P1 invalid. Therefore, the cache SHOULD announce the
sub-prefix P1 before the covering prefix P0.
*/
VRPi, VRPj := data[i].(*VRP), data[j].(*VRP)
CIDRSizei, _ := VRPi.Prefix.Mask.Size()
CIDRSizej, _ := VRPj.Prefix.Mask.Size()
if CIDRSizei == CIDRSizej {
if VRPi.MaxLen != VRPj.MaxLen {
return VRPi.MaxLen > VRPj.MaxLen
}
return bytes.Compare(VRPi.Prefix.IP, VRPj.Prefix.IP) < 1
} else {
return CIDRSizei > CIDRSizej
}
}
return true
})
pduBegin := &PDUCacheResponse{
SessionId: sessionId,
}