send-max: respect configuration

This commit is contained in:
Maxime Peim
2024-03-15 12:36:47 +01:00
committed by FUJITA Tomonori
parent bbde806641
commit 9fbc03765a
22 changed files with 1682 additions and 1394 deletions
+1211 -1200
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -544,6 +544,7 @@ message Path {
uint32 local_identifier = 19;
bytes nlri_binary = 20;
repeated bytes pattrs_binary = 21;
bool send_max_filtered = 22;
}
message Destination {
+21 -4
View File
@@ -586,7 +586,7 @@ func getPathAttributeString(nlri bgp.AddrPrefixInterface, attrs []bgp.PathAttrib
return fmt.Sprint(s)
}
func makeShowRouteArgs(p *api.Path, idx int, now time.Time, showAge, showBest, showLabel, showMUP bool, showIdentifier bgp.BGPAddPathMode) []interface{} {
func makeShowRouteArgs(p *api.Path, idx int, now time.Time, showAge, showBest, showLabel, showMUP, showSendMaxFiltered bool, showIdentifier bgp.BGPAddPathMode) []interface{} {
nlri, _ := apiutil.GetNativeNlri(p)
// Path Symbols (e.g. "*>")
@@ -650,17 +650,27 @@ func makeShowRouteArgs(p *api.Path, idx int, now time.Time, showAge, showBest, s
pattrstr := getPathAttributeString(nlri, attrs)
args = append(args, pattrstr)
if showSendMaxFiltered {
if p.SendMaxFiltered {
args = append(args, "send-max-filtered")
} else if p.Filtered {
args = append(args, "policy-filtered")
} else {
args = append(args, "not filtered")
}
}
updateColumnWidth(nlri.String(), nexthop, aspathstr, label, teid, qfi, endpoint)
return args
}
func showRoute(dsts []*api.Destination, showAge, showBest, showLabel, showMUP bool, showIdentifier bgp.BGPAddPathMode) {
func showRoute(dsts []*api.Destination, showAge, showBest, showLabel, showMUP, showSendMaxFiltered bool, showIdentifier bgp.BGPAddPathMode) {
pathStrs := make([][]interface{}, 0, len(dsts))
now := time.Now()
for _, dst := range dsts {
for idx, p := range dst.Paths {
pathStrs = append(pathStrs, makeShowRouteArgs(p, idx, now, showAge, showBest, showLabel, showMUP, showIdentifier))
pathStrs = append(pathStrs, makeShowRouteArgs(p, idx, now, showAge, showBest, showLabel, showMUP, showSendMaxFiltered, showIdentifier))
}
}
@@ -691,6 +701,11 @@ func showRoute(dsts []*api.Destination, showAge, showBest, showLabel, showMUP bo
headers = append(headers, "Attrs")
format += "%-s\n"
if showSendMaxFiltered {
headers = append(headers, "Filtered")
format += "%-s\n"
}
fmt.Printf(format, headers...)
for _, pathStr := range pathStrs {
fmt.Printf(format, pathStr...)
@@ -839,6 +854,7 @@ func showNeighborRib(r string, name string, args []string) error {
showAge := true
showLabel := false
showMUP := false
showSendMaxFiltered := false
showIdentifier := bgp.BGP_ADD_PATH_NONE
validationTarget := ""
rd := ""
@@ -852,6 +868,7 @@ func showNeighborRib(r string, name string, args []string) error {
showBest = true
case cmdAdjOut:
showAge = false
showSendMaxFiltered = true
case cmdVRF:
def = ipv4UC
showBest = true
@@ -1058,7 +1075,7 @@ func showNeighborRib(r string, name string, args []string) error {
}
}
if len(dsts) > 0 {
showRoute(dsts, showAge, showBest, showLabel, showMUP, showIdentifier)
showRoute(dsts, showAge, showBest, showLabel, showMUP, showSendMaxFiltered, showIdentifier)
} else {
fmt.Println("Network not in table")
}
+1 -4
View File
@@ -185,10 +185,7 @@ func rsFilter(id string, as uint32, path *Path) bool {
return false
}
if id != GLOBAL_RIB_NAME && (path.GetSource().Address.String() == id || isASLoop(as, path)) {
return true
}
return false
return id != GLOBAL_RIB_NAME && (path.GetSource().Address.String() == id || isASLoop(as, path))
}
func (dd *Destination) GetKnownPathList(id string, as uint32) []*Path {
+17 -2
View File
@@ -142,6 +142,15 @@ type Path struct {
IsNexthopInvalid bool
IsWithdraw bool
}
type FilteredType uint8
const (
NotFiltered FilteredType = 1 << iota
PolicyFiltered
SendMaxFiltered
)
type PathLocalKey string
var localSource = &PeerInfo{}
@@ -566,7 +575,7 @@ func (path *Path) String() string {
s.WriteString(fmt.Sprintf("{ %s EOR | src: %s }", path.GetRouteFamily(), path.GetSource()))
return s.String()
}
s.WriteString(fmt.Sprintf("{ %s | ", path.getPrefix()))
s.WriteString(fmt.Sprintf("{ %s | ", path.GetPrefix()))
s.WriteString(fmt.Sprintf("src: %s", path.GetSource()))
s.WriteString(fmt.Sprintf(", nh: %s", path.GetNexthop()))
if path.IsNexthopInvalid {
@@ -579,7 +588,13 @@ func (path *Path) String() string {
return s.String()
}
func (path *Path) getPrefix() 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()))
}
func (path *Path) GetPrefix() string {
return path.GetNlri().String()
}
+1 -1
View File
@@ -53,7 +53,7 @@ func TestPathGetPrefix(t *testing.T) {
peerP := PathCreatePeer()
pathP := PathCreatePath(peerP)
prefix := "10.10.10.0/24"
r_prefix := pathP[0].getPrefix()
r_prefix := pathP[0].GetPrefix()
assert.Equal(t, r_prefix, prefix)
}
+1 -1
View File
@@ -171,7 +171,7 @@ func (t *Table) validatePath(path *Path) {
log.Fields{
"Topic": "Table",
"Key": t.routeFamily,
"Prefix": path.GetNlri().String(),
"Prefix": path.GetPrefix(),
"ReceivedRf": path.GetRouteFamily().String()})
}
if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); attr != nil {
+26 -26
View File
@@ -118,7 +118,7 @@ func TestProcessBGPUpdate_0_select_onlypath_ipv4(t *testing.T) {
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "192.168.50.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -169,7 +169,7 @@ func TestProcessBGPUpdate_0_select_onlypath_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "2001::192:168:50:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -250,7 +250,7 @@ func TestProcessBGPUpdate_1_select_high_localpref_ipv4(t *testing.T) {
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "192.168.50.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -331,7 +331,7 @@ func TestProcessBGPUpdate_1_select_high_localpref_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "2001::192:168:100:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -414,7 +414,7 @@ func TestProcessBGPUpdate_2_select_local_origin_ipv4(t *testing.T) {
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "0.0.0.0"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -498,7 +498,7 @@ func TestProcessBGPUpdate_2_select_local_origin_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "::"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -554,7 +554,7 @@ func TestProcessBGPUpdate_3_select_aspath_ipv4(t *testing.T) {
// check destination
expectedPrefix := "20.20.20.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "192.168.100.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -610,7 +610,7 @@ func TestProcessBGPUpdate_3_select_aspath_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2002:223:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "2001::192:168:100:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -691,7 +691,7 @@ func TestProcessBGPUpdate_4_select_low_origin_ipv4(t *testing.T) {
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "192.168.100.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -772,7 +772,7 @@ func TestProcessBGPUpdate_4_select_low_origin_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "2001::192:168:100:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -853,7 +853,7 @@ func TestProcessBGPUpdate_5_select_low_med_ipv4(t *testing.T) {
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "192.168.100.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -934,7 +934,7 @@ func TestProcessBGPUpdate_5_select_low_med_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "2001::192:168:100:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1015,7 +1015,7 @@ func TestProcessBGPUpdate_6_select_ebgp_path_ipv4(t *testing.T) {
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "192.168.100.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1096,7 +1096,7 @@ func TestProcessBGPUpdate_6_select_ebgp_path_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "2001::192:168:100:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1180,7 +1180,7 @@ func TestProcessBGPUpdate_7_select_low_routerid_path_ipv4(t *testing.T) {
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "192.168.100.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1261,7 +1261,7 @@ func TestProcessBGPUpdate_7_select_low_routerid_path_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "2001::192:168:100:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1344,7 +1344,7 @@ func TestProcessBGPUpdate_8_withdraw_path_ipv4(t *testing.T) {
checkPattr(bgpMessage2, path)
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "192.168.100.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1365,7 +1365,7 @@ func TestProcessBGPUpdate_8_withdraw_path_ipv4(t *testing.T) {
checkPattr(bgpMessage1, path)
// check destination
expectedPrefix = "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop = "192.168.50.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1472,7 +1472,7 @@ func TestProcessBGPUpdate_8_mpunreach_path_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "2001::192:168:100:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1492,7 +1492,7 @@ func TestProcessBGPUpdate_8_mpunreach_path_ipv6(t *testing.T) {
checkPattr(bgpMessage1, path)
// check destination
expectedPrefix = "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop = "2001::192:168:50:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1567,7 +1567,7 @@ func TestProcessBGPUpdate_bestpath_lost_ipv4(t *testing.T) {
checkPattr(bgpMessage1, path)
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
}
func TestProcessBGPUpdate_bestpath_lost_ipv6(t *testing.T) {
@@ -1637,7 +1637,7 @@ func TestProcessBGPUpdate_bestpath_lost_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
}
// test: implicit withdrawal case
@@ -1715,7 +1715,7 @@ func TestProcessBGPUpdate_implicit_withdrwal_ipv4(t *testing.T) {
checkPattr(bgpMessage2, path)
// check destination
expectedPrefix := "10.10.10.0/24"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "192.168.50.1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1821,7 +1821,7 @@ func TestProcessBGPUpdate_implicit_withdrwal_ipv6(t *testing.T) {
// check destination
expectedPrefix := "2001:123:123:1::/64"
assert.Equal(t, expectedPrefix, path.getPrefix())
assert.Equal(t, expectedPrefix, path.GetPrefix())
// check nexthop
expectedNexthop := "2001::192:168:50:1"
assert.Equal(t, expectedNexthop, path.GetNexthop().String())
@@ -1876,7 +1876,7 @@ func TestProcessBGPUpdate_multiple_nlri_ipv4(t *testing.T) {
assert.Equal(t, p.GetRouteFamily(), rf)
checkPattr(m, p)
// check destination
assert.Equal(t, prefix, p.getPrefix())
assert.Equal(t, prefix, p.GetPrefix())
// check nexthop
assert.Equal(t, nexthop, p.GetNexthop().String())
}
@@ -2014,7 +2014,7 @@ func TestProcessBGPUpdate_multiple_nlri_ipv6(t *testing.T) {
assert.Equal(t, p.GetRouteFamily(), rf)
checkPattr(m, p)
// check destination
assert.Equal(t, prefix, p.getPrefix())
assert.Equal(t, prefix, p.GetPrefix())
// check nexthop
assert.Equal(t, nexthop, p.GetNexthop().String())
}
+19 -16
View File
@@ -28,14 +28,16 @@ import (
// workaround. This for the json format compatibility. Once we update senario tests, we can remove this.
type Path struct {
Nlri bgp.AddrPrefixInterface `json:"nlri"`
Age int64 `json:"age"`
Best bool `json:"best"`
Attrs []bgp.PathAttributeInterface `json:"attrs"`
Stale bool `json:"stale"`
Withdrawal bool `json:"withdrawal,omitempty"`
SourceID net.IP `json:"source-id,omitempty"`
NeighborIP net.IP `json:"neighbor-ip,omitempty"`
Nlri bgp.AddrPrefixInterface `json:"nlri"`
Age int64 `json:"age"`
Best bool `json:"best"`
Attrs []bgp.PathAttributeInterface `json:"attrs"`
Stale bool `json:"stale"`
// true if the path has been filtered out due to max path count reached
SendMaxFiltered bool `json:"send-max-filtered,omitempty"`
Withdrawal bool `json:"withdrawal,omitempty"`
SourceID net.IP `json:"source-id,omitempty"`
NeighborIP net.IP `json:"neighbor-ip,omitempty"`
}
type Destination struct {
@@ -52,14 +54,15 @@ func NewDestination(dst *api.Destination) *Destination {
nlri, _ := GetNativeNlri(p)
attrs, _ := GetNativePathAttributes(p)
l = append(l, &Path{
Nlri: nlri,
Age: p.Age.AsTime().Unix(),
Best: p.Best,
Attrs: attrs,
Stale: p.Stale,
Withdrawal: p.IsWithdraw,
SourceID: net.ParseIP(p.SourceId),
NeighborIP: net.ParseIP(p.NeighborIp),
Nlri: nlri,
Age: p.Age.AsTime().Unix(),
Best: p.Best,
Attrs: attrs,
Stale: p.Stale,
SendMaxFiltered: p.SendMaxFiltered,
Withdrawal: p.IsWithdraw,
SourceID: net.ParseIP(p.SourceId),
NeighborIP: net.ParseIP(p.NeighborIp),
})
}
return &Destination{Paths: l}
+137 -12
View File
@@ -98,21 +98,25 @@ 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
llgrEndChs []chan 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
sendMaxPathFiltered map[table.PathLocalKey]struct{}
llgrEndChs []chan struct{}
}
func newPeer(g *oc.Global, conf *oc.Neighbor, loc *table.TableManager, policy *table.RoutingPolicy, logger log.Logger) *peer {
peer := &peer{
localRib: loc,
policy: policy,
fsm: newFSM(g, conf, logger),
prefixLimitWarned: make(map[bgp.RouteFamily]bool),
localRib: loc,
policy: policy,
fsm: newFSM(g, conf, logger),
prefixLimitWarned: make(map[bgp.RouteFamily]bool),
dstRoutesCount: make(map[bgp.RouteFamily]map[string]uint8),
sendMaxPathFiltered: make(map[table.PathLocalKey]struct{}),
}
if peer.isRouteServerClient() {
peer.tableId = conf.State.NeighborAddress
@@ -200,6 +204,128 @@ func (peer *peer) isAddPathSendEnabled(family bgp.RouteFamily) bool {
return (peer.getAddPathMode(family) & bgp.BGP_ADD_PATH_SEND) > 0
}
func (peer *peer) getAddPathSendMax(family bgp.RouteFamily) uint8 {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
for _, a := range peer.fsm.pConf.AfiSafis {
if a.State.Family == family {
return a.AddPaths.Config.SendMax
}
}
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]
}
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 {
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
}
peer.dstRoutesCount[family][dstPrefix] = newCount
}
func (peer *peer) isPathSendMaxFiltered(path *table.Path) bool {
if path == nil {
return false
}
_, found := peer.sendMaxPathFiltered[path.GetLocalKey()]
return found
}
func (peer *peer) unsetPathSendMaxFiltered(path *table.Path) bool {
if path == nil {
return false
}
if _, ok := peer.sendMaxPathFiltered[path.GetLocalKey()]; !ok {
return false
}
delete(peer.sendMaxPathFiltered, path.GetLocalKey())
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 {
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{}{}
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
}
func (peer *peer) isDynamicNeighbor() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
@@ -440,7 +566,6 @@ func (peer *peer) doPrefixLimit(k bgp.RouteFamily, c *oc.PrefixLimitConfig) *bgp
}
}
return nil
}
func (peer *peer) updatePrefixLimitConfig(c []oc.AfiSafi) error {
+72 -20
View File
@@ -760,13 +760,14 @@ func (s *BgpServer) postFilterpath(peer *peer, path *table.Path) *table.Path {
if path != nil && !peer.isIBGPPeer() && !peer.isRouteServerClient() {
path.RemoveLocalPref()
}
return path
}
func (s *BgpServer) filterpath(peer *peer, path, old *table.Path) *table.Path {
path, options, stop := s.prePolicyFilterpath(peer, path, old)
if stop {
return path
return nil
}
options.Validate = s.roaTable.Validate
path = peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, path, options)
@@ -1138,7 +1139,6 @@ func (s *BgpServer) processOutgoingPaths(peer *peer, paths, olds []*table.Path)
}
outgoing := make([]*table.Path, 0, len(paths))
for idx, path := range paths {
var old *table.Path
if olds != nil {
@@ -1291,7 +1291,7 @@ func (s *BgpServer) propagateUpdate(peer *peer, pathList []*table.Path) {
}
if dsts := rib.Update(path); len(dsts) > 0 {
s.propagateUpdateToNeighbors(peer, path, dsts, true)
s.propagateUpdateToNeighbors(rib, peer, path, dsts, true)
}
}
}
@@ -1312,7 +1312,7 @@ func dstsToPaths(id string, as uint32, dsts []*table.Update) ([]*table.Path, []*
return bestList, oldList, mpathList
}
func (s *BgpServer) propagateUpdateToNeighbors(source *peer, newPath *table.Path, dsts []*table.Update, needOld bool) {
func (s *BgpServer) propagateUpdateToNeighbors(rib *table.TableManager, source *peer, newPath *table.Path, dsts []*table.Update, needOld bool) {
if table.SelectionOptions.DisableBestPathSelection {
return
}
@@ -1350,11 +1350,41 @@ func (s *BgpServer) propagateUpdateToNeighbors(source *peer, newPath *table.Path
bestList = func() []*table.Path {
l := make([]*table.Path, 0, len(dsts))
for _, d := range dsts {
l = append(l, d.GetWithdrawnPath()...)
toDelete := d.GetWithdrawnPath()
toActuallyDelete := make([]*table.Path, 0, len(toDelete))
for _, p := range toDelete {
// the path was never advertized to the peer
if targetPeer.unsetPathSendMaxFiltered(p) {
continue
}
toActuallyDelete = append(toActuallyDelete, p)
}
if len(toActuallyDelete) == 0 {
continue
}
destination := rib.GetDestination(toActuallyDelete[0])
dstPrefix := toActuallyDelete[0].GetPrefix()
targetPeer.decrementRoutesCount(dstPrefix, f, uint8(len(toActuallyDelete)))
l = append(l, toActuallyDelete...)
// the destination has been removed from the table
// e.g. no more paths to it
if destination == nil {
continue
}
toAdd := targetPeer.getSendMaxFilteredPathList(destination, len(toActuallyDelete))
targetPeer.incrementRoutesCount(dstPrefix, f, uint8(len(toAdd)))
for _, p := range toAdd {
targetPeer.unsetPathSendMaxFiltered(p)
}
l = append(l, toAdd...)
}
return l
}()
} else {
} else if targetPeer.canSendPathWithinLimit(newPath) {
bestList = []*table.Path{newPath}
if newPath.GetRouteFamily() == bgp.RF_RTC_UC {
// we assumes that new "path" nlri was already sent before. This assumption avoids the
@@ -1366,6 +1396,14 @@ func (s *BgpServer) propagateUpdateToNeighbors(source *peer, newPath *table.Path
}
}
}
} else {
bestList = []*table.Path{}
s.logger.Warn("exceeding max routes for prefix",
log.Fields{
"Topic": "Peer",
"Key": targetPeer.ID(),
"Prefix": newPath.GetPrefix(),
})
}
oldList = nil
} else if targetPeer.isRouteServerClient() {
@@ -2161,7 +2199,7 @@ func (s *BgpServer) fixupApiPath(vrfId string, pathList []*table.Path) error {
}
func pathTokey(path *table.Path) string {
return fmt.Sprintf("%d:%s", path.GetNlri().PathIdentifier(), path.GetNlri().String())
return fmt.Sprintf("%d:%s", path.GetNlri().PathIdentifier(), path.GetPrefix())
}
func (s *BgpServer) addPathList(vrfId string, pathList []*table.Path) error {
@@ -2631,7 +2669,7 @@ func (s *BgpServer) getVrfRib(name string, family bgp.RouteFamily, prefixes []*t
return
}
func (s *BgpServer) getAdjRib(addr string, family bgp.RouteFamily, in bool, enableFiltered bool, prefixes []*table.LookupPrefix) (rib *table.Table, filtered map[string]*table.Path, v map[*table.Path]*table.Validation, err error) {
func (s *BgpServer) getAdjRib(addr string, family bgp.RouteFamily, in bool, enableFiltered bool, prefixes []*table.LookupPrefix) (rib *table.Table, filtered map[table.PathLocalKey]table.FilteredType, v map[*table.Path]*table.Validation, err error) {
err = s.mgmtOperation(func() error {
peer, ok := s.neighborMap[addr]
if !ok {
@@ -2641,23 +2679,26 @@ func (s *BgpServer) getAdjRib(addr string, family bgp.RouteFamily, in bool, enab
as := peer.AS()
var adjRib *table.AdjRib
filtered = make(map[string]*table.Path)
var toUpdate []*table.Path
filtered = make(map[table.PathLocalKey]table.FilteredType)
if in {
adjRib = peer.adjRibIn
if enableFiltered {
toUpdate = make([]*table.Path, 0)
for _, path := range peer.adjRibIn.PathList([]bgp.RouteFamily{family}, true) {
options := &table.PolicyOptions{
Validate: s.roaTable.Validate,
}
if p := s.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_IMPORT, path, options); p == nil {
filtered[path.GetNlri().String()] = path
filtered[path.GetLocalKey()] = table.PolicyFiltered
} else {
adjRib.Update([]*table.Path{p})
toUpdate = append(toUpdate, p)
}
}
}
} else {
adjRib = table.NewAdjRib(s.logger, peer.configuredRFlist())
pathList := make([]*table.Path, 0)
if enableFiltered {
for _, path := range s.getPossibleBest(peer, family) {
path, options, stop := s.prePolicyFilterpath(peer, path, nil)
@@ -2667,15 +2708,23 @@ func (s *BgpServer) getAdjRib(addr string, family bgp.RouteFamily, in bool, enab
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
filtered[path.GetLocalKey()] = table.PolicyFiltered
}
adjRib.UpdateAdjRibOut([]*table.Path{path})
pathList = append(pathList, path)
}
} else {
accepted, _ := s.getBestFromLocal(peer, peer.configuredRFlist())
adjRib.UpdateAdjRibOut(accepted)
pathList, _ = s.getBestFromLocal(peer, peer.configuredRFlist())
}
toUpdate = make([]*table.Path, 0, len(pathList))
for _, p := range pathList {
pathLocalKey := p.GetLocalKey()
if peer.isPathSendMaxFiltered(p) {
filtered[pathLocalKey] = filtered[pathLocalKey] | table.SendMaxFiltered
}
toUpdate = append(toUpdate, p)
}
}
adjRib.Update(toUpdate)
rib, err = adjRib.Select(family, false, table.TableSelectOption{ID: id, AS: as, LookupPrefixes: prefixes})
v = s.validateTable(rib)
return err
@@ -2689,7 +2738,7 @@ func (s *BgpServer) ListPath(ctx context.Context, r *api.ListPathRequest, fn fun
}
var tbl *table.Table
var v map[*table.Path]*table.Validation
var filtered map[string]*table.Path
var filtered map[table.PathLocalKey]table.FilteredType
f := func() []*table.LookupPrefix {
l := make([]*table.LookupPrefix, 0, len(r.Prefixes))
@@ -2747,10 +2796,13 @@ func (s *BgpServer) ListPath(ctx context.Context, r *api.ListPathRequest, fn fun
}
}
d.Paths = append(d.Paths, p)
if r.EnableFiltered {
if _, ok := filtered[path.GetNlri().String()]; ok {
p.Filtered = true
}
if r.EnableFiltered && filtered[path.GetLocalKey()]&table.PolicyFiltered > 0 {
p.Filtered = true
}
// we always want to know that some paths are filtered out
// by send-max attribute
if filtered[path.GetLocalKey()]&table.SendMaxFiltered > 0 {
p.SendMaxFiltered = true
}
}
+1 -1
View File
@@ -142,7 +142,7 @@ func newIPRouteBody(dst []*table.Path, vrfID uint32, z *zebraClient) (body *zebr
}
path := paths[0]
l := strings.SplitN(path.GetNlri().String(), "/", 2)
l := strings.SplitN(path.GetPrefix(), "/", 2)
var prefix net.IP
var nexthop zebra.Nexthop
nexthops := make([]zebra.Nexthop, 0, len(paths))
+33 -12
View File
@@ -128,15 +128,14 @@ def wait_for_completion(f, timeout=120):
def try_several_times(f, t=3, s=1):
e = Exception
for _ in range(t):
try:
r = f()
except RuntimeError as e:
except RuntimeError:
time.sleep(s)
else:
return r
raise e
raise Exception
def assert_several_times(f, t=30, s=1):
@@ -144,8 +143,9 @@ def assert_several_times(f, t=30, s=1):
for _ in range(t):
try:
f()
except AssertionError as e:
except AssertionError as ae:
time.sleep(s)
e = ae
else:
return
raise e
@@ -361,14 +361,35 @@ class BGPContainer(Container):
raise Exception('peer not exists')
self.add_peer(peer, **kwargs)
def add_peer(self, peer, passwd=None, vpn=False, is_rs_client=False,
policies=None, passive=False,
is_rr_client=False, cluster_id=None,
flowspec=False, bridge='', reload_config=True, as2=False,
graceful_restart=None, local_as=None, prefix_limit=None,
v6=False, llgr=None, vrf='', interface='', allow_as_in=0,
remove_private_as=None, replace_peer_as=False, addpath=False,
treat_as_withdraw=False, remote_as=None, mup=False):
def add_peer(
self,
peer,
passwd=None,
vpn=False,
is_rs_client=False,
policies=None,
passive=False,
is_rr_client=False,
cluster_id=None,
flowspec=False,
bridge="",
reload_config=True,
as2=False,
graceful_restart=None,
local_as=None,
prefix_limit=None,
v6=False,
llgr=None,
vrf="",
interface="",
allow_as_in=0,
remove_private_as=None,
replace_peer_as=False,
addpath=0,
treat_as_withdraw=False,
remote_as=None,
mup=False,
):
neigh_addr = ''
local_addr = ''
it = itertools.product(self.ip_addrs, peer.ip_addrs)
+1 -1
View File
@@ -76,7 +76,7 @@ class ExaBGPContainer(BGPContainer):
caps = []
if info['as2']:
caps.append(' asn4 disable;')
if info['addpath']:
if info["addpath"] > 0:
caps.append(' add-path send/receive;')
if caps:
cmd << ' capability {'
+10 -10
View File
@@ -14,7 +14,6 @@
# limitations under the License.
import collections
import json
from itertools import chain
@@ -484,9 +483,10 @@ class GoBGPContainer(BGPContainer):
n['route-reflector'] = {'config': {'route-reflector-client': True,
'route-reflector-cluster-id': cluster_id}}
if info['addpath']:
n['add-paths'] = {'config': {'receive': True,
'send-max': 16}}
if info["addpath"] > 0:
n["add-paths"] = {
"config": {"receive": True, "send-max": info["addpath"]}
}
if len(info.get('default-policy', [])) + len(info.get('policies', [])) > 0:
n['apply-policy'] = {'config': {}}
@@ -536,11 +536,11 @@ class GoBGPContainer(BGPContainer):
with open('{0}/gobgpd.conf'.format(self.config_dir), 'w') as f:
print(yellow('[{0}\'s new gobgpd.conf]'.format(self.name)))
if self.config_format is 'toml':
if self.config_format == "toml":
raw = toml.dumps(config)
elif self.config_format is 'yaml':
elif self.config_format == "yaml":
raw = yaml.dump(config)
elif self.config_format is 'json':
elif self.config_format == "json":
raw = json.dumps(config)
else:
raise Exception('invalid config_format {0}'.format(self.config_format))
@@ -666,11 +666,11 @@ class GoBGPContainer(BGPContainer):
class RawGoBGPContainer(GoBGPContainer):
def __init__(self, name, config, ctn_image_name='osrg/gobgp',
log_level='debug', zebra=False, config_format='yaml'):
if config_format is 'toml':
if config_format == "toml":
d = toml.loads(config)
elif config_format is 'yaml':
elif config_format == "yaml":
d = yaml.load(config)
elif config_format is 'json':
elif config_format == "json":
d = json.loads(config)
else:
raise Exception('invalid config format {0}'.format(config_format))
+85 -64
View File
@@ -14,6 +14,7 @@
# limitations under the License.
import sys
import json
import time
import unittest
@@ -34,6 +35,8 @@ from lib.noseplugin import OptionParser, parser_option
class GoBGPTestBase(unittest.TestCase):
SEND_MAX = 5
INSTALLED_PATHS = SEND_MAX + 1
@classmethod
def setUpClass(cls):
@@ -56,14 +59,14 @@ class GoBGPTestBase(unittest.TestCase):
time.sleep(initial_wait_time)
g1.add_peer(e1, addpath=True)
e1.add_peer(g1, addpath=True)
g1.add_peer(e1, addpath=16)
e1.add_peer(g1, addpath=16)
g1.add_peer(g2, addpath=False, is_rr_client=True)
g2.add_peer(g1, addpath=False)
g1.add_peer(g2, is_rr_client=True)
g2.add_peer(g1)
g1.add_peer(g3, addpath=True, is_rr_client=True)
g3.add_peer(g1, addpath=True)
g1.add_peer(g3, addpath=cls.SEND_MAX, is_rr_client=True)
g3.add_peer(g1, addpath=cls.SEND_MAX)
cls.g1 = g1
cls.g2 = g2
@@ -73,20 +76,26 @@ class GoBGPTestBase(unittest.TestCase):
# test each neighbor state is turned establish
def test_00_neighbor_established(self):
self.g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=self.g2)
self.g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=self.g3)
self.g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=self.e1)
# prepare routes with path_id (no error check)
def test_01_prepare_add_paths_routes(self):
self.e1.add_route(route='192.168.100.0/24', identifier=10, aspath=[100, 200, 300])
self.e1.add_route(route='192.168.100.0/24', identifier=20, aspath=[100, 200])
self.e1.add_route(route='192.168.100.0/24', identifier=30, aspath=[100])
aspath = []
for i in range(self.INSTALLED_PATHS):
aspath.append((i + 1) * 100)
self.e1.add_route(
route="192.168.100.0/24",
identifier=(i + 1) * 10,
aspath=aspath,
)
# test three routes are installed to the rib due to add-path feature
def test_02_check_g1_global_rib(self):
def f():
rib = self.g1.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 3)
self.assertEqual(len(rib[0]["paths"]), self.INSTALLED_PATHS)
assert_several_times(f)
@@ -96,7 +105,7 @@ class GoBGPTestBase(unittest.TestCase):
rib = self.g2.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 1)
self.assertEqual(rib[0]['paths'][0]['aspath'], [100])
self.assertEqual(len(rib[0]["paths"][0]["aspath"]), 1)
assert_several_times(f)
@@ -105,167 +114,179 @@ class GoBGPTestBase(unittest.TestCase):
def f():
rib = self.g3.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 3)
self.assertEqual(len(rib[0]["paths"]), self.SEND_MAX)
assert_several_times(f)
def test_05_check_g1_adj_out(self):
adj_out = self.g1.get_adj_rib_out(self.g2, add_path_enabled=True)
self.assertEqual(len(adj_out), 1)
self.assertEqual(len(adj_out[0]["paths"]), 1)
adj_out = self.g1.get_adj_rib_out(self.g3, add_path_enabled=True)
self.assertEqual(len(adj_out), 1)
self.assertEqual(len(adj_out[0]["paths"]), self.INSTALLED_PATHS)
# expect the last path to be filtered
self.assertTrue(adj_out[0]["paths"][-1].get("send-max-filtered", False))
# withdraw a route with path_id (no error check)
def test_05_withdraw_route_with_path_id(self):
self.e1.del_route(route='192.168.100.0/24', identifier=30)
def test_06_withdraw_route_with_path_id(self):
self.e1.del_route(route="192.168.100.0/24", identifier=10)
# test the withdrawn route is removed from the rib
def test_06_check_g1_global_rib(self):
def test_07_check_g1_global_rib(self):
def f():
rib = self.g1.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 2)
self.assertEqual(len(rib[0]["paths"]), self.INSTALLED_PATHS - 1)
# we deleted the highest priority path
for path in rib[0]['paths']:
self.assertIn(path['aspath'], ([100, 200, 300],
[100, 200]))
self.assertTrue(2 <= len(path["aspath"]) <= self.INSTALLED_PATHS)
assert_several_times(f)
# test the best path is replaced due to the removal from g1 rib
def test_07_check_g2_global_rib(self):
def test_08_check_g2_global_rib(self):
def f():
rib = self.g2.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 1)
self.assertEqual(rib[0]['paths'][0]['aspath'], [100, 200])
self.assertEqual(len(rib[0]["paths"][0]["aspath"]), 2)
assert_several_times(f)
# test the withdrawn route is removed from the rib of g3
def test_08_check_g3_global_rib(self):
# and the filtered route is advertised to g3
def test_09_check_g3_global_rib(self):
def f():
rib = self.g3.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 2)
self.assertEqual(len(rib[0]["paths"]), self.SEND_MAX)
for path in rib[0]['paths']:
self.assertIn(path['aspath'], ([100, 200, 300],
[100, 200]))
self.assertTrue(2 <= len(path["aspath"]) <= self.INSTALLED_PATHS)
assert_several_times(f)
# install a route with path_id via GoBGP CLI (no error check)
def test_09_install_add_paths_route_via_cli(self):
def test_10_install_add_paths_route_via_cli(self):
# identifier is duplicated with the identifier of the route from e1
self.g1.add_route(route='192.168.100.0/24', identifier=10, local_pref=500)
# test the route from CLI is installed to the rib
def test_10_check_g1_global_rib(self):
def test_11_check_g1_global_rib(self):
def f():
rib = self.g1.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 3)
self.assertEqual(len(rib[0]["paths"]), self.INSTALLED_PATHS)
for path in rib[0]['paths']:
self.assertIn(path['aspath'], ([100, 200, 300],
[100, 200],
[]))
if not path['aspath']: # path['aspath'] == []
if not path["aspath"]:
self.assertEqual(path['local-pref'], 500)
else:
self.assertTrue(2 <= len(path["aspath"]) <= self.INSTALLED_PATHS)
assert_several_times(f)
def test_11_check_g1_adj_out(self):
def test_12_check_g1_adj_out(self):
adj_out = self.g1.get_adj_rib_out(self.g2, add_path_enabled=True)
self.assertEqual(len(adj_out), 1)
self.assertEqual(len(adj_out[0]['paths']), 1)
self.assertEqual(len(adj_out[0]["paths"]), 1)
adj_out = self.g1.get_adj_rib_out(self.g3, add_path_enabled=True)
self.assertEqual(len(adj_out), 1)
self.assertEqual(len(adj_out[0]['paths']), 3)
self.assertEqual(len(adj_out[0]["paths"]), self.INSTALLED_PATHS)
print(json.dumps(adj_out, indent=2))
# the new best path shouldn't be advertised as it is added after
# the limit is reached
self.assertEqual(adj_out[0]["paths"][0]["local-pref"], 500)
self.assertTrue(adj_out[0]["paths"][0].get("send-max-filtered", False))
# test the best path is replaced due to the CLI route from g1 rib
def test_12_check_g2_global_rib(self):
def test_13_check_g2_global_rib(self):
def f():
rib = self.g2.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 1)
self.assertEqual(rib[0]['paths'][0]['aspath'], [])
self.assertEqual(len(rib[0]["paths"][0]["aspath"]), 0)
self.assertEqual(rib[0]["paths"][0]["local-pref"], 500)
assert_several_times(f)
# test the route from CLI is advertised from g1
def test_13_check_g3_global_rib(self):
def test_14_check_g3_global_rib(self):
def f():
rib = self.g3.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 3)
print(json.dumps(rib, indent=2))
self.assertEqual(len(rib[0]["paths"]), self.SEND_MAX)
for path in rib[0]['paths']:
self.assertIn(path['aspath'], ([100, 200, 300],
[100, 200],
[]))
if not path['aspath']: # path['aspath'] == []
self.assertEqual(path['local-pref'], 500)
self.assertTrue(2 <= len(path["aspath"]) <= self.INSTALLED_PATHS)
assert_several_times(f)
# remove non-existing route with path_id via GoBGP CLI (no error check)
def test_14_remove_non_existing_add_paths_route_via_cli(self):
def test_15_remove_non_existing_add_paths_route_via_cli(self):
# specify locally non-existing identifier which has the same value
# with the identifier of the route from e1
self.g1.del_route(route='192.168.100.0/24', identifier=20)
# test none of route is removed by non-existing path_id via CLI
def test_15_check_g1_global_rib(self):
def test_16_check_g1_global_rib(self):
def f():
rib = self.g1.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 3)
self.assertEqual(len(rib[0]["paths"]), self.INSTALLED_PATHS)
for path in rib[0]['paths']:
self.assertIn(path['aspath'], ([100, 200, 300],
[100, 200],
[]))
if not path['aspath']: # path['aspath'] == []
if not path["aspath"]:
self.assertEqual(path['local-pref'], 500)
else:
self.assertTrue(2 <= len(path["aspath"]) <= self.INSTALLED_PATHS)
assert_several_times(f)
# remove route with path_id via GoBGP CLI (no error check)
def test_16_remove_add_paths_route_via_cli(self):
def test_17_remove_add_paths_route_via_cli(self):
self.g1.del_route(route='192.168.100.0/24', identifier=10)
def test_17_check_g1_adj_out(self):
def test_18_check_g1_adj_out(self):
adj_out = self.g1.get_adj_rib_out(self.g2, add_path_enabled=True)
self.assertEqual(len(adj_out), 1)
self.assertEqual(len(adj_out[0]['paths']), 1)
self.assertEqual(len(adj_out[0]["paths"]), 1)
adj_out = self.g1.get_adj_rib_out(self.g3, add_path_enabled=True)
self.assertEqual(len(adj_out), 1)
self.assertEqual(len(adj_out[0]['paths']), 2)
self.assertEqual(len(adj_out[0]["paths"]), self.INSTALLED_PATHS - 1)
# test the route is removed from the rib via CLI
def test_18_check_g1_global_rib(self):
def test_19_check_g1_global_rib(self):
def f():
rib = self.g1.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 2)
self.assertEqual(len(rib[0]["paths"]), self.INSTALLED_PATHS - 1)
for path in rib[0]['paths']:
self.assertIn(path['aspath'], ([100, 200, 300],
[100, 200]))
if not path["aspath"]:
self.assertTrue(2 <= len(path["aspath"]) <= self.INSTALLED_PATHS)
assert_several_times(f)
# test the best path is replaced the removal from g1 rib
def test_19_check_g2_global_rib(self):
def test_20_check_g2_global_rib(self):
def f():
rib = self.g2.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 1)
self.assertEqual(rib[0]['paths'][0]['aspath'], [100, 200])
self.assertEqual(len(rib[0]["paths"][0]["aspath"]), 2)
assert_several_times(f)
# test the removed route from CLI is withdrawn by g1
def test_20_check_g3_global_rib(self):
def test_21_check_g3_global_rib(self):
def f():
rib = self.g3.get_global_rib()
self.assertEqual(len(rib), 1)
self.assertEqual(len(rib[0]['paths']), 2)
self.assertEqual(len(rib[0]["paths"]), self.SEND_MAX)
for path in rib[0]['paths']:
self.assertIn(path['aspath'], ([100, 200, 300],
[100, 200]))
if not path["aspath"]:
self.assertTrue(2 <= len(path["aspath"]) <= self.INSTALLED_PATHS)
assert_several_times(f)
-2
View File
@@ -480,7 +480,6 @@ class GoBGPTestBase(unittest.TestCase):
self.gobgp.add_peer(q6, passwd='password')
q6.add_peer(self.gobgp, passwd='password')
self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q6)
def test_25_add_quagga_md5_badpass(self):
@@ -575,7 +574,6 @@ class GoBGPTestBase(unittest.TestCase):
# note that we are checking it on the Quagga side since GoBGP
# config doesn't explicitly "know about" the peer
q9.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g6, timeout=30)
if __name__ == '__main__':
+36 -8
View File
@@ -162,17 +162,45 @@ class GoBGPTestBase(unittest.TestCase):
time.sleep(max(ctn.run() for ctn in [rr, acme1, acme2, tyrell1, tyrell2]))
rr.add_peer(acme1, vpn=True, addpath=True, graceful_restart=True, llgr=True, is_rr_client=True)
acme1.add_peer(rr, vpn=True, addpath=True, graceful_restart=True, llgr=True)
rr.add_peer(
acme1,
vpn=True,
addpath=16,
graceful_restart=True,
llgr=True,
is_rr_client=True,
)
acme1.add_peer(rr, vpn=True, addpath=16, graceful_restart=True, llgr=True)
rr.add_peer(acme2, vpn=True, addpath=True, graceful_restart=True, llgr=True, is_rr_client=True)
acme2.add_peer(rr, vpn=True, addpath=True, graceful_restart=True, llgr=True)
rr.add_peer(
acme2,
vpn=True,
addpath=16,
graceful_restart=True,
llgr=True,
is_rr_client=True,
)
acme2.add_peer(rr, vpn=True, addpath=16, graceful_restart=True, llgr=True)
rr.add_peer(tyrell1, vpn=True, addpath=True, graceful_restart=True, llgr=True, is_rr_client=True)
tyrell1.add_peer(rr, vpn=True, addpath=True, graceful_restart=True, llgr=True)
rr.add_peer(
tyrell1,
vpn=True,
addpath=16,
graceful_restart=True,
llgr=True,
is_rr_client=True,
)
tyrell1.add_peer(rr, vpn=True, addpath=16, graceful_restart=True, llgr=True)
rr.add_peer(tyrell2, vpn=True, addpath=True, graceful_restart=True, llgr=True, is_rr_client=True)
tyrell2.add_peer(rr, vpn=True, addpath=True, graceful_restart=True, llgr=True)
rr.add_peer(
tyrell2,
vpn=True,
addpath=16,
graceful_restart=True,
llgr=True,
is_rr_client=True,
)
tyrell2.add_peer(rr, vpn=True, addpath=16, graceful_restart=True, llgr=True)
self.__class__.rr = rr
self.__class__.acme1 = acme1
@@ -91,7 +91,6 @@ class GoBGPTestBase(unittest.TestCase):
state = self.gobgp.get_neighbor_state(rs_client)
self.assertEqual(state, BGP_FSM_ESTABLISHED)
local_rib = self.gobgp.get_local_rib(rs_client)
local_rib = [p['prefix'] for p in local_rib]
if len(local_rib) < (len(self.quaggas) - 1):
time.sleep(self.wait_per_retry)
continue
@@ -87,7 +87,7 @@ class GoBGPIPv6Test(unittest.TestCase):
state = self.gobgp.get_neighbor_state(rs_client)
self.assertEqual(state, BGP_FSM_ESTABLISHED)
local_rib = self.gobgp.get_local_rib(rs_client, rf=rf)
local_rib = [p['prefix'] for p in local_rib]
local_rib = [p["prefix"] for p in local_rib]
if len(local_rib) < (len(ctns) - 1):
time.sleep(self.wait_per_retry)
continue
+4 -4
View File
@@ -841,11 +841,11 @@ class GoBGPTestBase(unittest.TestCase):
# +-------------+ +-------------+
g3, g4, g5 = self.g3, self.g4, self.g5
g3.update_peer(g4, vpn=True, addpath=True, is_rr_client=True)
g4.update_peer(g3, vpn=True, addpath=True)
g3.update_peer(g4, vpn=True, addpath=16, is_rr_client=True)
g4.update_peer(g3, vpn=True, addpath=16)
g3.update_peer(g5, vpn=True, addpath=True, is_rr_client=True)
g5.update_peer(g3, vpn=True, addpath=True)
g3.update_peer(g5, vpn=True, addpath=16, is_rr_client=True)
g5.update_peer(g3, vpn=True, addpath=16)
g3.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g4)
g3.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g5)
+4 -4
View File
@@ -55,10 +55,10 @@ class GoBGPTestBase(unittest.TestCase):
time.sleep(initial_wait_time)
g1.add_peer(g2, vpn=True, addpath=True)
g2.add_peer(g1, vpn=True, addpath=True)
g1.add_peer(g3, vpn=True, addpath=True)
g3.add_peer(g1, vpn=True, addpath=True)
g1.add_peer(g2, vpn=True, addpath=16)
g2.add_peer(g1, vpn=True, addpath=16)
g1.add_peer(g3, vpn=True, addpath=16)
g3.add_peer(g1, vpn=True, addpath=16)
cls.g1 = g1
cls.g2 = g2