Skip to content

Commit

Permalink
fix send-max limit in case of route update
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxime Peim committed Jun 3, 2024
1 parent 076e9fc commit da54b33
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 169 deletions.
31 changes: 28 additions & 3 deletions internal/pkg/table/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ type Path struct {
IsNexthopInvalid bool
IsWithdraw bool
}

type FilteredType uint8

const (
Expand All @@ -150,7 +151,21 @@ const (
SendMaxFiltered
)

type PathLocalKey string
type PathDestLocalKey struct {
Family bgp.RouteFamily
Prefix string
}
type PathLocalKey struct {
PathDestLocalKey
Id uint32
}

func NewPathDestLocalKey(f bgp.RouteFamily, destPrefix string) *PathDestLocalKey {
return &PathDestLocalKey{
Family: f,
Prefix: destPrefix,
}
}

var localSource = &PeerInfo{}

Expand Down Expand Up @@ -590,8 +605,18 @@ func (path *Path) String() string {

// GetLocalKey identifies the path in the local BGP server.
func (path *Path) GetLocalKey() PathLocalKey {
// return PathLocalKey(path.GetPrefix())
return PathLocalKey(fmt.Sprintf("%s:%s:%d", path.GetRouteFamily(), path.GetNlri(), path.GetNlri().PathLocalIdentifier()))
return PathLocalKey{
PathDestLocalKey: path.GetDestLocalKey(),
Id: path.GetNlri().PathLocalIdentifier(),
}
}

// GetDestLocalKey identifies the path destination in the local BGP server.
func (path *Path) GetDestLocalKey() PathDestLocalKey {
return PathDestLocalKey{
Family: path.GetRouteFamily(),
Prefix: path.GetNlri().String(),
}
}

func (path *Path) GetPrefix() string {
Expand Down
7 changes: 5 additions & 2 deletions pkg/packet/bgp/bgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,7 @@ const (
BGP_RD_TWO_OCTET_AS = iota
BGP_RD_IPV4_ADDRESS
BGP_RD_FOUR_OCTET_AS
BGP_RD_EOR
)

type RouteDistinguisherInterface interface {
Expand Down Expand Up @@ -9637,6 +9638,8 @@ func NewPrefixFromRouteFamily(afi uint16, safi uint8, prefixStr ...string) (pref
return NewIPv6AddrPrefix(uint8(len), addr.String()), nil
}

rdEOR := &RouteDistinguisherUnknown{DefaultRouteDistinguisher{Type: BGP_RD_EOR}, []byte("EOR")}

switch family {
case RF_IPv4_UC, RF_IPv4_MC:
if len(prefixStr) > 0 {
Expand All @@ -9652,7 +9655,7 @@ func NewPrefixFromRouteFamily(afi uint16, safi uint8, prefixStr ...string) (pref
}
case RF_IPv4_VPN:
if len(prefixStr) == 0 {
prefix = NewLabeledVPNIPAddrPrefix(0, "", *NewMPLSLabelStack(), nil)
prefix = NewLabeledVPNIPAddrPrefix(0, "", *NewMPLSLabelStack(), rdEOR)
break
}

Expand All @@ -9671,7 +9674,7 @@ func NewPrefixFromRouteFamily(afi uint16, safi uint8, prefixStr ...string) (pref
)
case RF_IPv6_VPN:
if len(prefixStr) == 0 {
prefix = NewLabeledVPNIPv6AddrPrefix(0, "", *NewMPLSLabelStack(), nil)
prefix = NewLabeledVPNIPv6AddrPrefix(0, "", *NewMPLSLabelStack(), rdEOR)
break
}

Expand Down
124 changes: 40 additions & 84 deletions pkg/server/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,14 @@ func newDynamicPeer(g *oc.Global, neighborAddress string, pg *oc.PeerGroup, loc
}

type peer struct {
tableId string
fsm *fsm
adjRibIn *table.AdjRib
policy *table.RoutingPolicy
localRib *table.TableManager
prefixLimitWarned map[bgp.RouteFamily]bool
dstRoutesCount map[bgp.RouteFamily]map[string]uint8
tableId string
fsm *fsm
adjRibIn *table.AdjRib
policy *table.RoutingPolicy
localRib *table.TableManager
prefixLimitWarned map[bgp.RouteFamily]bool
// map of path local identifiers sent for that prefix
sentPaths map[table.PathDestLocalKey]map[uint32]struct{}
sendMaxPathFiltered map[table.PathLocalKey]struct{}
llgrEndChs []chan struct{}
}
Expand All @@ -115,7 +116,7 @@ func newPeer(g *oc.Global, conf *oc.Neighbor, loc *table.TableManager, policy *t
policy: policy,
fsm: newFSM(g, conf, logger),
prefixLimitWarned: make(map[bgp.RouteFamily]bool),
dstRoutesCount: make(map[bgp.RouteFamily]map[string]uint8),
sentPaths: make(map[table.PathDestLocalKey]map[uint32]struct{}),
sendMaxPathFiltered: make(map[table.PathLocalKey]struct{}),
}
if peer.isRouteServerClient() {
Expand Down Expand Up @@ -215,56 +216,39 @@ func (peer *peer) getAddPathSendMax(family bgp.RouteFamily) uint8 {
return 0
}

func (peer *peer) getRoutesCount(dstPrefix string, family bgp.RouteFamily) uint8 {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
if _, ok := peer.dstRoutesCount[family]; ok {
return peer.dstRoutesCount[family][dstPrefix]
func (peer *peer) getRoutesCount(family bgp.RouteFamily, dstPrefix string) uint8 {
destLocalKey := table.NewPathDestLocalKey(family, dstPrefix)
if identifiers, ok := peer.sentPaths[*destLocalKey]; ok {
count := len(identifiers)
// the send-max config is uint8, so we need to check for overflow
if count > int(^uint8(0)) {
return ^uint8(0)
}
return uint8(count)
}
return 0
}

func (peer *peer) setRoutesCount(dstPrefix string, family bgp.RouteFamily, count uint8) {
peer.fsm.lock.Lock()
defer peer.fsm.lock.Unlock()
if _, ok := peer.dstRoutesCount[family]; !ok {
peer.dstRoutesCount[family] = make(map[string]uint8)
}
peer.dstRoutesCount[family][dstPrefix] = count
}

func (peer *peer) incrementRoutesCount(dstPrefix string, family bgp.RouteFamily, inc uint8) {
if inc == 0 {
return
}

peer.fsm.lock.Lock()
defer peer.fsm.lock.Unlock()
if _, ok := peer.dstRoutesCount[family]; !ok {
peer.dstRoutesCount[family] = make(map[string]uint8)
}
newCount := peer.dstRoutesCount[family][dstPrefix] + inc
if newCount < peer.dstRoutesCount[family][dstPrefix] {
newCount = 0xFF
}
peer.dstRoutesCount[family][dstPrefix] = newCount
}

func (peer *peer) decrementRoutesCount(dstPrefix string, family bgp.RouteFamily, dec uint8) {
if dec == 0 {
func (peer *peer) updateRoutes(paths ...*table.Path) {
if len(paths) == 0 {
return
}

peer.fsm.lock.Lock()
defer peer.fsm.lock.Unlock()
if _, ok := peer.dstRoutesCount[family]; !ok {
peer.dstRoutesCount[family] = make(map[string]uint8)
}
newCount := peer.dstRoutesCount[family][dstPrefix] - dec
if newCount > peer.dstRoutesCount[family][dstPrefix] {
newCount = 0
for _, path := range paths {
localKey := path.GetLocalKey()
destLocalKey := localKey.PathDestLocalKey
identifiers, destExists := peer.sentPaths[destLocalKey]
if path.IsWithdraw && destExists {
delete(identifiers, path.GetNlri().PathLocalIdentifier())
} else if !path.IsWithdraw {
if !destExists {
peer.sentPaths[destLocalKey] = make(map[uint32]struct{})
}
identifiers := peer.sentPaths[destLocalKey]
if len(identifiers) < int(peer.getAddPathSendMax(destLocalKey.Family)) {
identifiers[localKey.Id] = struct{}{}
}
}
}
peer.dstRoutesCount[family][dstPrefix] = newCount
}

func (peer *peer) isPathSendMaxFiltered(path *table.Path) bool {
Expand All @@ -286,44 +270,16 @@ func (peer *peer) unsetPathSendMaxFiltered(path *table.Path) bool {
return true
}

func (peer *peer) getSendMaxFilteredPathList(dest *table.Destination, limit int) []*table.Path {
knownPathList := dest.GetKnownPathList(peer.TableID(), peer.AS())
list := make([]*table.Path, 0, len(knownPathList))
for _, p := range knownPathList {
if !peer.isPathSendMaxFiltered(p) {
continue
}
list = append(list, p)
if limit > 0 && len(list) == limit {
break
}
}
return list
}

func (peer *peer) canSendPathWithinLimit(path *table.Path) bool {
func (peer *peer) hasPathAlreadyBeenSent(path *table.Path) bool {
if path == nil {
return false
}

family := path.GetRouteFamily()
dstPrefix := path.GetPrefix()
sendMax := peer.getAddPathSendMax(family)
dstRouteCount := peer.getRoutesCount(dstPrefix, family)

if dstRouteCount >= sendMax {
peer.sendMaxPathFiltered[path.GetLocalKey()] = struct{}{}
destLocalKey := path.GetDestLocalKey()
if _, dstExist := peer.sentPaths[destLocalKey]; !dstExist {
return false
}

if dstRouteCount > 0 && path.IsWithdraw {
peer.decrementRoutesCount(dstPrefix, family, 1)
} else if dstRouteCount < sendMax && !path.IsWithdraw {
peer.incrementRoutesCount(dstPrefix, family, 1)
} else {
return false
}
return true
_, pathExist := peer.sentPaths[destLocalKey][path.GetNlri().PathLocalIdentifier()]
return pathExist
}

func (peer *peer) isDynamicNeighbor() bool {
Expand Down
Loading

0 comments on commit da54b33

Please sign in to comment.