diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go index 1859f665c0a96904c5a5cd2c4e7d4d7dfe640c08..f75ce7a0c4403e8d1530c198099d2cbefa605923 100644 --- a/protocols/bgp/packet/bgp.go +++ b/protocols/bgp/packet/bgp.go @@ -10,6 +10,7 @@ const ( HeaderLen = 19 MinLen = 19 MaxLen = 4096 + MinUpdateLen = 4 NLRIMaxLen = 5 CommunityLen = 4 LargeCommunityLen = 12 diff --git a/protocols/bgp/server/BUILD.bazel b/protocols/bgp/server/BUILD.bazel index 792d140d13132ece8f5b86e0f8597328eb39f0df..631671e09122407f96bf8bf012840bc1e7d99391 100644 --- a/protocols/bgp/server/BUILD.bazel +++ b/protocols/bgp/server/BUILD.bazel @@ -47,6 +47,7 @@ go_test( "fsm_test.go", "server_test.go", "update_helper_test.go", + "update_sender_test.go", "withdraw_test.go", ], embed = [":go_default_library"], diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go index 31a065e8e3703df3b518c7c7051e602133482f9e..e30d2bdf2480aec484ba6481911dced753c29f9a 100644 --- a/protocols/bgp/server/fsm_established.go +++ b/protocols/bgp/server/fsm_established.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "net" + "time" bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/protocols/bgp/packet" @@ -85,14 +86,10 @@ func (s *establishedState) init() error { clientOptions := routingtable.ClientOptions{ BestOnly: true, } - if s.fsm.options.AddPathRX { - s.fsm.updateSender = newUpdateSenderAddPath(s.fsm) - clientOptions = s.fsm.peer.addPathSend - } else { - s.fsm.updateSender = newUpdateSender(s.fsm) - } - s.fsm.updateSender.Start() + s.fsm.updateSender = newUpdateSender(s.fsm) + s.fsm.updateSender.Start(time.Millisecond * 5) + s.fsm.adjRIBOut.Register(s.fsm.updateSender) s.fsm.rib.RegisterWithOptions(s.fsm.adjRIBOut, clientOptions) diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go index c2df04afbe40280cc19d1251abccc6a54b33ffdf..63c3c7eb4e57b7fe44c3df83141ce539797a05ce 100644 --- a/protocols/bgp/server/update_sender.go +++ b/protocols/bgp/server/update_sender.go @@ -4,12 +4,12 @@ import ( "sync" "time" - log "github.com/sirupsen/logrus" - - bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/protocols/bgp/packet" "github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/routingtable" + + bnet "github.com/bio-routing/bio-rd/net" + log "github.com/sirupsen/logrus" ) // UpdateSender converts table changes into BGP update messages @@ -17,7 +17,6 @@ type UpdateSender struct { routingtable.ClientManager fsm *FSM iBGP bool - addPath bool toSendMu sync.Mutex toSend map[string]*pathPfxs destroyCh chan struct{} @@ -28,12 +27,6 @@ type pathPfxs struct { pfxs []bnet.Prefix } -func newUpdateSenderAddPath(fsm *FSM) *UpdateSender { - u := newUpdateSender(fsm) - u.addPath = true - return u -} - func newUpdateSender(fsm *FSM) *UpdateSender { return &UpdateSender{ fsm: fsm, @@ -44,8 +37,8 @@ func newUpdateSender(fsm *FSM) *UpdateSender { } // Start starts the update sender -func (u *UpdateSender) Start() { - go u.sender() +func (u *UpdateSender) Start(aggrTime time.Duration) { + go u.sender(aggrTime) } // Destroy destroys everything (with greetings to Hatebreed) @@ -76,8 +69,8 @@ func (u *UpdateSender) AddPath(pfx bnet.Prefix, p *route.Path) error { } // sender serializes BGP update messages -func (u *UpdateSender) sender() { - ticker := time.NewTicker(time.Millisecond * 5) +func (u *UpdateSender) sender(aggrTime time.Duration) { + ticker := time.NewTicker(aggrTime) var err error var pathAttrs *packet.PathAttribute var budget int @@ -92,24 +85,28 @@ func (u *UpdateSender) sender() { u.toSendMu.Lock() for key, pathNLRIs := range u.toSend { - budget = packet.MaxLen - int(pathNLRIs.path.BGPPath.Length()) + budget = packet.MaxLen - packet.HeaderLen - packet.MinUpdateLen - int(pathNLRIs.path.BGPPath.Length()) pathAttrs, err = packet.PathAttributes(pathNLRIs.path) if err != nil { log.Errorf("Unable to get path attributes: %v", err) continue } - updatesPrefixes := make([][]bnet.Prefix, 1) - prefixes := make([]bnet.Prefix, 1) + updatesPrefixes := make([][]bnet.Prefix, 0, 1) + prefixes := make([]bnet.Prefix, 0, 1) for _, pfx := range pathNLRIs.pfxs { - budget -= int(packet.BytesInAddr(pfx.Pfxlen())) - 5 + budget -= int(packet.BytesInAddr(pfx.Pfxlen())) + 1 if budget < 0 { updatesPrefixes = append(updatesPrefixes, prefixes) - prefixes = make([]bnet.Prefix, 1) + prefixes = make([]bnet.Prefix, 0, 1) + budget = packet.MaxLen - int(pathNLRIs.path.BGPPath.Length()) } prefixes = append(prefixes, pfx) } + if len(prefixes) > 0 { + updatesPrefixes = append(updatesPrefixes, prefixes) + } delete(u.toSend, key) u.toSendMu.Unlock() @@ -150,7 +147,11 @@ func (u *UpdateSender) sendUpdates(pathAttrs *packet.PathAttribute, updatePrefix // RemovePath withdraws prefix `pfx` from a peer func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool { err := withDrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p) - return err == nil + if err != nil { + log.Errorf("Unable to withdraw prefix: %v", err) + return false + } + return true } // UpdateNewClient does nothing diff --git a/protocols/bgp/server/update_sender_test.go b/protocols/bgp/server/update_sender_test.go new file mode 100644 index 0000000000000000000000000000000000000000..1683c23d12434c711edeb5f2d62bd54882709303 --- /dev/null +++ b/protocols/bgp/server/update_sender_test.go @@ -0,0 +1,393 @@ +package server + +import ( + "net" + "reflect" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + bnet "github.com/bio-routing/bio-rd/net" + "github.com/bio-routing/bio-rd/protocols/bgp/types" + "github.com/bio-routing/bio-rd/route" + "github.com/bio-routing/bio-rd/routingtable/filter" + "github.com/bio-routing/bio-rd/routingtable/locRIB" + btest "github.com/bio-routing/bio-rd/testing" +) + +func TestSender(t *testing.T) { + tests := []struct { + name string + paths []pathPfxs + generateNLRIs uint64 + expectedUpdates [][]byte + addPath bool + }{ + { + name: "Two paths with 3 NLRIs each", + paths: []pathPfxs{ + { + path: &route.Path{ + Type: 2, + BGPPath: &route.BGPPath{ + LocalPref: 100, + }, + }, + pfxs: []bnet.Prefix{ + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{10, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{11, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{12, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{13, 0, 0, 0})), 32), + }, + }, + { + path: &route.Path{ + Type: 2, + BGPPath: &route.BGPPath{ + LocalPref: 200, + }, + }, + pfxs: []bnet.Prefix{ + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{20, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{21, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{22, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{23, 0, 0, 0})), 8), + }, + }, + }, + expectedUpdates: [][]byte{ + { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 52, + 2, + 0, 0, 0, 21, 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 200, + 8, 23, 8, 22, 8, 21, 8, 20, + + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 55, + 2, + 0, 0, 0, 21, 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 100, + 32, 13, 0, 0, 0, 8, 12, 8, 11, 8, 10, + }, + { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 55, + 2, + 0, 0, 0, 21, 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 100, + 32, 13, 0, 0, 0, 8, 12, 8, 11, 8, 10, + + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 52, + 2, + 0, 0, 0, 21, 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 200, + 8, 23, 8, 22, 8, 21, 8, 20, + }, + }, + }, + { + name: "Two paths with 3 NLRIs each with BGP Add Path", + addPath: true, + paths: []pathPfxs{ + { + path: &route.Path{ + Type: 2, + BGPPath: &route.BGPPath{ + LocalPref: 100, + }, + }, + pfxs: []bnet.Prefix{ + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{10, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{11, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{12, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{13, 0, 0, 0})), 32), + }, + }, + { + path: &route.Path{ + Type: 2, + BGPPath: &route.BGPPath{ + LocalPref: 200, + }, + }, + pfxs: []bnet.Prefix{ + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{20, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{21, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{22, 0, 0, 0})), 8), + bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{23, 0, 0, 0})), 8), + }, + }, + }, + expectedUpdates: [][]byte{ + { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 71, + 2, + 0, 0, + 0, 21, 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 100, + 0, 0, 0, 0, 32, 13, 0, 0, 0, + 0, 0, 0, 0, 8, 12, + 0, 0, 0, 0, 8, 11, + 0, 0, 0, 0, 8, 10, + + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 68, + 2, + 0, 0, + 0, 21, 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 200, + 0, 0, 0, 0, 8, 23, + 0, 0, 0, 0, 8, 22, + 0, 0, 0, 0, 8, 21, + 0, 0, 0, 0, 8, 20, + }, + { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 68, + 2, + 0, 0, + 0, 21, 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 200, + 0, 0, 0, 0, 8, 23, + 0, 0, 0, 0, 8, 22, + 0, 0, 0, 0, 8, 21, + 0, 0, 0, 0, 8, 20, + + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 71, + 2, + 0, 0, + 0, 21, 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 100, + 0, 0, 0, 0, 32, 13, 0, 0, 0, + 0, 0, 0, 0, 8, 12, + 0, 0, 0, 0, 8, 11, + 0, 0, 0, 0, 8, 10, + }, + }, + }, + { + name: "Overflow. Too many NLRIs.", + paths: []pathPfxs{ + { + path: &route.Path{ + Type: 2, + BGPPath: &route.BGPPath{ + LocalPref: 100, + }, + }, + }, + }, + generateNLRIs: 1000, + expectedUpdates: [][]byte{ + { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 15, 239, 2, 0, 0, 0, 21, 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 100, + 32, 10, 0, 3, 35, 32, 10, 0, 3, 34, 32, 10, 0, 3, 33, 32, 10, 0, 3, 32, 32, 10, 0, 3, 31, 32, 10, 0, 3, 30, 32, 10, 0, 3, 29, + 32, 10, 0, 3, 28, 32, 10, 0, 3, 27, 32, 10, 0, 3, 26, 32, 10, 0, 3, 25, 32, 10, 0, 3, 24, 32, 10, 0, 3, 23, 32, 10, 0, 3, 22, + 32, 10, 0, 3, 21, 32, 10, 0, 3, 20, 32, 10, 0, 3, 19, 32, 10, 0, 3, 18, 32, 10, 0, 3, 17, 32, 10, 0, 3, 16, 32, 10, 0, 3, 15, + 32, 10, 0, 3, 14, 32, 10, 0, 3, 13, 32, 10, 0, 3, 12, 32, 10, 0, 3, 11, 32, 10, 0, 3, 10, 32, 10, 0, 3, 9, 32, 10, 0, 3, 8, + 32, 10, 0, 3, 7, 32, 10, 0, 3, 6, 32, 10, 0, 3, 5, 32, 10, 0, 3, 4, 32, 10, 0, 3, 3, 32, 10, 0, 3, 2, 32, 10, 0, 3, 1, + 32, 10, 0, 3, 0, 32, 10, 0, 3, 255, 32, 10, 0, 3, 254, 32, 10, 0, 3, 253, 32, 10, 0, 2, 253, 32, 10, 0, 2, 252, 32, 10, 0, 2, 251, + 32, 10, 0, 2, 250, 32, 10, 0, 2, 249, 32, 10, 0, 2, 248, 32, 10, 0, 2, 247, 32, 10, 0, 2, 246, 32, 10, 0, 2, 245, 32, 10, 0, 2, 244, + 32, 10, 0, 2, 243, 32, 10, 0, 2, 242, 32, 10, 0, 2, 241, 32, 10, 0, 2, 240, 32, 10, 0, 2, 239, 32, 10, 0, 2, 238, 32, 10, 0, 2, 237, + 32, 10, 0, 2, 236, 32, 10, 0, 2, 235, 32, 10, 0, 2, 234, 32, 10, 0, 2, 233, 32, 10, 0, 2, 232, 32, 10, 0, 2, 231, 32, 10, 0, 2, 230, + 32, 10, 0, 2, 229, 32, 10, 0, 2, 228, 32, 10, 0, 2, 227, 32, 10, 0, 2, 226, 32, 10, 0, 2, 225, 32, 10, 0, 2, 224, 32, 10, 0, 2, 223, + 32, 10, 0, 2, 222, 32, 10, 0, 2, 221, 32, 10, 0, 2, 220, 32, 10, 0, 2, 219, 32, 10, 0, 2, 218, 32, 10, 0, 2, 217, 32, 10, 0, 2, 216, + 32, 10, 0, 2, 215, 32, 10, 0, 2, 214, 32, 10, 0, 2, 213, 32, 10, 0, 2, 212, 32, 10, 0, 2, 211, 32, 10, 0, 2, 210, 32, 10, 0, 2, 209, + 32, 10, 0, 2, 208, 32, 10, 0, 2, 207, 32, 10, 0, 2, 206, 32, 10, 0, 2, 205, 32, 10, 0, 2, 204, 32, 10, 0, 2, 203, 32, 10, 0, 2, 202, + 32, 10, 0, 2, 201, 32, 10, 0, 2, 200, 32, 10, 0, 2, 199, 32, 10, 0, 2, 198, 32, 10, 0, 2, 197, 32, 10, 0, 2, 196, 32, 10, 0, 2, 195, + 32, 10, 0, 2, 194, 32, 10, 0, 2, 193, 32, 10, 0, 2, 192, 32, 10, 0, 2, 191, 32, 10, 0, 2, 190, 32, 10, 0, 2, 189, 32, 10, 0, 2, 188, + 32, 10, 0, 2, 187, 32, 10, 0, 2, 186, 32, 10, 0, 2, 185, 32, 10, 0, 2, 184, 32, 10, 0, 2, 183, 32, 10, 0, 2, 182, 32, 10, 0, 2, 181, + 32, 10, 0, 2, 180, 32, 10, 0, 2, 179, 32, 10, 0, 2, 178, 32, 10, 0, 2, 177, 32, 10, 0, 2, 176, 32, 10, 0, 2, 175, 32, 10, 0, 2, 174, + 32, 10, 0, 2, 173, 32, 10, 0, 2, 172, 32, 10, 0, 2, 171, 32, 10, 0, 2, 170, 32, 10, 0, 2, 169, 32, 10, 0, 2, 168, 32, 10, 0, 2, 167, + 32, 10, 0, 2, 166, 32, 10, 0, 2, 165, 32, 10, 0, 2, 164, 32, 10, 0, 2, 163, 32, 10, 0, 2, 162, 32, 10, 0, 2, 161, 32, 10, 0, 2, 160, + 32, 10, 0, 2, 159, 32, 10, 0, 2, 158, 32, 10, 0, 2, 157, 32, 10, 0, 2, 156, 32, 10, 0, 2, 155, 32, 10, 0, 2, 154, 32, 10, 0, 2, 153, + 32, 10, 0, 2, 152, 32, 10, 0, 2, 151, 32, 10, 0, 2, 150, 32, 10, 0, 2, 149, 32, 10, 0, 2, 148, 32, 10, 0, 2, 147, 32, 10, 0, 2, 146, + 32, 10, 0, 2, 145, 32, 10, 0, 2, 144, 32, 10, 0, 2, 143, 32, 10, 0, 2, 142, 32, 10, 0, 2, 141, 32, 10, 0, 2, 140, 32, 10, 0, 2, 139, + 32, 10, 0, 2, 138, 32, 10, 0, 2, 137, 32, 10, 0, 2, 136, 32, 10, 0, 2, 135, 32, 10, 0, 2, 134, 32, 10, 0, 2, 133, 32, 10, 0, 2, 132, + 32, 10, 0, 2, 131, 32, 10, 0, 2, 130, 32, 10, 0, 2, 129, 32, 10, 0, 2, 128, 32, 10, 0, 2, 127, 32, 10, 0, 2, 126, 32, 10, 0, 2, 125, + 32, 10, 0, 2, 124, 32, 10, 0, 2, 123, 32, 10, 0, 2, 122, 32, 10, 0, 2, 121, 32, 10, 0, 2, 120, 32, 10, 0, 2, 119, 32, 10, 0, 2, 118, + 32, 10, 0, 2, 117, 32, 10, 0, 2, 116, 32, 10, 0, 2, 115, 32, 10, 0, 2, 114, 32, 10, 0, 2, 113, 32, 10, 0, 2, 112, 32, 10, 0, 2, 111, + 32, 10, 0, 2, 110, 32, 10, 0, 2, 109, 32, 10, 0, 2, 108, 32, 10, 0, 2, 107, 32, 10, 0, 2, 106, 32, 10, 0, 2, 105, 32, 10, 0, 2, 104, + 32, 10, 0, 2, 103, 32, 10, 0, 2, 102, 32, 10, 0, 2, 101, 32, 10, 0, 2, 100, 32, 10, 0, 2, 99, 32, 10, 0, 2, 98, 32, 10, 0, 2, 97, + 32, 10, 0, 2, 96, 32, 10, 0, 2, 95, 32, 10, 0, 2, 94, 32, 10, 0, 2, 93, 32, 10, 0, 2, 92, 32, 10, 0, 2, 91, 32, 10, 0, 2, 90, + 32, 10, 0, 2, 89, 32, 10, 0, 2, 88, 32, 10, 0, 2, 87, 32, 10, 0, 2, 86, 32, 10, 0, 2, 85, 32, 10, 0, 2, 84, 32, 10, 0, 2, 83, + 32, 10, 0, 2, 82, 32, 10, 0, 2, 81, 32, 10, 0, 2, 80, 32, 10, 0, 2, 79, 32, 10, 0, 2, 78, 32, 10, 0, 2, 77, 32, 10, 0, 2, 76, + 32, 10, 0, 2, 75, 32, 10, 0, 2, 74, 32, 10, 0, 2, 73, 32, 10, 0, 2, 72, 32, 10, 0, 2, 71, 32, 10, 0, 2, 70, 32, 10, 0, 2, 69, + 32, 10, 0, 2, 68, 32, 10, 0, 2, 67, 32, 10, 0, 2, 66, 32, 10, 0, 2, 65, 32, 10, 0, 2, 64, 32, 10, 0, 2, 63, 32, 10, 0, 2, 62, + 32, 10, 0, 2, 61, 32, 10, 0, 2, 60, 32, 10, 0, 2, 59, 32, 10, 0, 2, 58, 32, 10, 0, 2, 57, 32, 10, 0, 2, 56, 32, 10, 0, 2, 55, + 32, 10, 0, 2, 54, 32, 10, 0, 2, 53, 32, 10, 0, 2, 52, 32, 10, 0, 2, 51, 32, 10, 0, 2, 50, 32, 10, 0, 2, 49, 32, 10, 0, 2, 48, + 32, 10, 0, 2, 47, 32, 10, 0, 2, 46, 32, 10, 0, 2, 45, 32, 10, 0, 2, 44, 32, 10, 0, 2, 43, 32, 10, 0, 2, 42, 32, 10, 0, 2, 41, + 32, 10, 0, 2, 40, 32, 10, 0, 2, 39, 32, 10, 0, 2, 38, 32, 10, 0, 2, 37, 32, 10, 0, 2, 36, 32, 10, 0, 2, 35, 32, 10, 0, 2, 34, + 32, 10, 0, 2, 33, 32, 10, 0, 2, 32, 32, 10, 0, 2, 31, 32, 10, 0, 2, 30, 32, 10, 0, 2, 29, 32, 10, 0, 2, 28, 32, 10, 0, 2, 27, + 32, 10, 0, 2, 26, 32, 10, 0, 2, 25, 32, 10, 0, 2, 24, 32, 10, 0, 2, 23, 32, 10, 0, 2, 22, 32, 10, 0, 2, 21, 32, 10, 0, 2, 20, + 32, 10, 0, 2, 19, 32, 10, 0, 2, 18, 32, 10, 0, 2, 17, 32, 10, 0, 2, 16, 32, 10, 0, 2, 15, 32, 10, 0, 2, 14, 32, 10, 0, 2, 13, + 32, 10, 0, 2, 12, 32, 10, 0, 2, 11, 32, 10, 0, 2, 10, 32, 10, 0, 2, 9, 32, 10, 0, 2, 8, 32, 10, 0, 2, 7, 32, 10, 0, 2, 6, + 32, 10, 0, 2, 5, 32, 10, 0, 2, 4, 32, 10, 0, 2, 3, 32, 10, 0, 2, 2, 32, 10, 0, 2, 1, 32, 10, 0, 2, 0, 32, 10, 0, 2, 255, + 32, 10, 0, 2, 254, 32, 10, 0, 1, 254, 32, 10, 0, 1, 253, 32, 10, 0, 1, 252, 32, 10, 0, 1, 251, 32, 10, 0, 1, 250, 32, 10, 0, 1, 249, + 32, 10, 0, 1, 248, 32, 10, 0, 1, 247, 32, 10, 0, 1, 246, 32, 10, 0, 1, 245, 32, 10, 0, 1, 244, 32, 10, 0, 1, 243, 32, 10, 0, 1, 242, + 32, 10, 0, 1, 241, 32, 10, 0, 1, 240, 32, 10, 0, 1, 239, 32, 10, 0, 1, 238, 32, 10, 0, 1, 237, 32, 10, 0, 1, 236, 32, 10, 0, 1, 235, + 32, 10, 0, 1, 234, 32, 10, 0, 1, 233, 32, 10, 0, 1, 232, 32, 10, 0, 1, 231, 32, 10, 0, 1, 230, 32, 10, 0, 1, 229, 32, 10, 0, 1, 228, + 32, 10, 0, 1, 227, 32, 10, 0, 1, 226, 32, 10, 0, 1, 225, 32, 10, 0, 1, 224, 32, 10, 0, 1, 223, 32, 10, 0, 1, 222, 32, 10, 0, 1, 221, + 32, 10, 0, 1, 220, 32, 10, 0, 1, 219, 32, 10, 0, 1, 218, 32, 10, 0, 1, 217, 32, 10, 0, 1, 216, 32, 10, 0, 1, 215, 32, 10, 0, 1, 214, + 32, 10, 0, 1, 213, 32, 10, 0, 1, 212, 32, 10, 0, 1, 211, 32, 10, 0, 1, 210, 32, 10, 0, 1, 209, 32, 10, 0, 1, 208, 32, 10, 0, 1, 207, + 32, 10, 0, 1, 206, 32, 10, 0, 1, 205, 32, 10, 0, 1, 204, 32, 10, 0, 1, 203, 32, 10, 0, 1, 202, 32, 10, 0, 1, 201, 32, 10, 0, 1, 200, + 32, 10, 0, 1, 199, 32, 10, 0, 1, 198, 32, 10, 0, 1, 197, 32, 10, 0, 1, 196, 32, 10, 0, 1, 195, 32, 10, 0, 1, 194, 32, 10, 0, 1, 193, + 32, 10, 0, 1, 192, 32, 10, 0, 1, 191, 32, 10, 0, 1, 190, 32, 10, 0, 1, 189, 32, 10, 0, 1, 188, 32, 10, 0, 1, 187, 32, 10, 0, 1, 186, + 32, 10, 0, 1, 185, 32, 10, 0, 1, 184, 32, 10, 0, 1, 183, 32, 10, 0, 1, 182, 32, 10, 0, 1, 181, 32, 10, 0, 1, 180, 32, 10, 0, 1, 179, + 32, 10, 0, 1, 178, 32, 10, 0, 1, 177, 32, 10, 0, 1, 176, 32, 10, 0, 1, 175, 32, 10, 0, 1, 174, 32, 10, 0, 1, 173, 32, 10, 0, 1, 172, + 32, 10, 0, 1, 171, 32, 10, 0, 1, 170, 32, 10, 0, 1, 169, 32, 10, 0, 1, 168, 32, 10, 0, 1, 167, 32, 10, 0, 1, 166, 32, 10, 0, 1, 165, + 32, 10, 0, 1, 164, 32, 10, 0, 1, 163, 32, 10, 0, 1, 162, 32, 10, 0, 1, 161, 32, 10, 0, 1, 160, 32, 10, 0, 1, 159, 32, 10, 0, 1, 158, + 32, 10, 0, 1, 157, 32, 10, 0, 1, 156, 32, 10, 0, 1, 155, 32, 10, 0, 1, 154, 32, 10, 0, 1, 153, 32, 10, 0, 1, 152, 32, 10, 0, 1, 151, + 32, 10, 0, 1, 150, 32, 10, 0, 1, 149, 32, 10, 0, 1, 148, 32, 10, 0, 1, 147, 32, 10, 0, 1, 146, 32, 10, 0, 1, 145, 32, 10, 0, 1, 144, + 32, 10, 0, 1, 143, 32, 10, 0, 1, 142, 32, 10, 0, 1, 141, 32, 10, 0, 1, 140, 32, 10, 0, 1, 139, 32, 10, 0, 1, 138, 32, 10, 0, 1, 137, + 32, 10, 0, 1, 136, 32, 10, 0, 1, 135, 32, 10, 0, 1, 134, 32, 10, 0, 1, 133, 32, 10, 0, 1, 132, 32, 10, 0, 1, 131, 32, 10, 0, 1, 130, + 32, 10, 0, 1, 129, 32, 10, 0, 1, 128, 32, 10, 0, 1, 127, 32, 10, 0, 1, 126, 32, 10, 0, 1, 125, 32, 10, 0, 1, 124, 32, 10, 0, 1, 123, + 32, 10, 0, 1, 122, 32, 10, 0, 1, 121, 32, 10, 0, 1, 120, 32, 10, 0, 1, 119, 32, 10, 0, 1, 118, 32, 10, 0, 1, 117, 32, 10, 0, 1, 116, + 32, 10, 0, 1, 115, 32, 10, 0, 1, 114, 32, 10, 0, 1, 113, 32, 10, 0, 1, 112, 32, 10, 0, 1, 111, 32, 10, 0, 1, 110, 32, 10, 0, 1, 109, + 32, 10, 0, 1, 108, 32, 10, 0, 1, 107, 32, 10, 0, 1, 106, 32, 10, 0, 1, 105, 32, 10, 0, 1, 104, 32, 10, 0, 1, 103, 32, 10, 0, 1, 102, + 32, 10, 0, 1, 101, 32, 10, 0, 1, 100, 32, 10, 0, 1, 99, 32, 10, 0, 1, 98, 32, 10, 0, 1, 97, 32, 10, 0, 1, 96, 32, 10, 0, 1, 95, + 32, 10, 0, 1, 94, 32, 10, 0, 1, 93, 32, 10, 0, 1, 92, 32, 10, 0, 1, 91, 32, 10, 0, 1, 90, 32, 10, 0, 1, 89, 32, 10, 0, 1, 88, + 32, 10, 0, 1, 87, 32, 10, 0, 1, 86, 32, 10, 0, 1, 85, 32, 10, 0, 1, 84, 32, 10, 0, 1, 83, 32, 10, 0, 1, 82, 32, 10, 0, 1, 81, + 32, 10, 0, 1, 80, 32, 10, 0, 1, 79, 32, 10, 0, 1, 78, 32, 10, 0, 1, 77, 32, 10, 0, 1, 76, 32, 10, 0, 1, 75, 32, 10, 0, 1, 74, + 32, 10, 0, 1, 73, 32, 10, 0, 1, 72, 32, 10, 0, 1, 71, 32, 10, 0, 1, 70, 32, 10, 0, 1, 69, 32, 10, 0, 1, 68, 32, 10, 0, 1, 67, + 32, 10, 0, 1, 66, 32, 10, 0, 1, 65, 32, 10, 0, 1, 64, 32, 10, 0, 1, 63, 32, 10, 0, 1, 62, 32, 10, 0, 1, 61, 32, 10, 0, 1, 60, + 32, 10, 0, 1, 59, 32, 10, 0, 1, 58, 32, 10, 0, 1, 57, 32, 10, 0, 1, 56, 32, 10, 0, 1, 55, 32, 10, 0, 1, 54, 32, 10, 0, 1, 53, + 32, 10, 0, 1, 52, 32, 10, 0, 1, 51, 32, 10, 0, 1, 50, 32, 10, 0, 1, 49, 32, 10, 0, 1, 48, 32, 10, 0, 1, 47, 32, 10, 0, 1, 46, + 32, 10, 0, 1, 45, 32, 10, 0, 1, 44, 32, 10, 0, 1, 43, 32, 10, 0, 1, 42, 32, 10, 0, 1, 41, 32, 10, 0, 1, 40, 32, 10, 0, 1, 39, + 32, 10, 0, 1, 38, 32, 10, 0, 1, 37, 32, 10, 0, 1, 36, 32, 10, 0, 1, 35, 32, 10, 0, 1, 34, 32, 10, 0, 1, 33, 32, 10, 0, 1, 32, + 32, 10, 0, 1, 31, 32, 10, 0, 1, 30, 32, 10, 0, 1, 29, 32, 10, 0, 1, 28, 32, 10, 0, 1, 27, 32, 10, 0, 1, 26, 32, 10, 0, 1, 25, + 32, 10, 0, 1, 24, 32, 10, 0, 1, 23, 32, 10, 0, 1, 22, 32, 10, 0, 1, 21, 32, 10, 0, 1, 20, 32, 10, 0, 1, 19, 32, 10, 0, 1, 18, + 32, 10, 0, 1, 17, 32, 10, 0, 1, 16, 32, 10, 0, 1, 15, 32, 10, 0, 1, 14, 32, 10, 0, 1, 13, 32, 10, 0, 1, 12, 32, 10, 0, 1, 11, + 32, 10, 0, 1, 10, 32, 10, 0, 1, 9, 32, 10, 0, 1, 8, 32, 10, 0, 1, 7, 32, 10, 0, 1, 6, 32, 10, 0, 1, 5, 32, 10, 0, 1, 4, + 32, 10, 0, 1, 3, 32, 10, 0, 1, 2, 32, 10, 0, 1, 1, 32, 10, 0, 1, 0, 32, 10, 0, 1, 255, 32, 10, 0, 0, 255, 32, 10, 0, 0, 254, 32, 10, 0, 0, 253, + 32, 10, 0, 0, 252, 32, 10, 0, 0, 251, 32, 10, 0, 0, 250, 32, 10, 0, 0, 249, 32, 10, 0, 0, 248, 32, 10, 0, 0, 247, 32, 10, 0, 0, 246, + 32, 10, 0, 0, 245, 32, 10, 0, 0, 244, 32, 10, 0, 0, 243, 32, 10, 0, 0, 242, 32, 10, 0, 0, 241, 32, 10, 0, 0, 240, 32, 10, 0, 0, 239, + 32, 10, 0, 0, 238, 32, 10, 0, 0, 237, 32, 10, 0, 0, 236, 32, 10, 0, 0, 235, 32, 10, 0, 0, 234, 32, 10, 0, 0, 233, 32, 10, 0, 0, 232, + 32, 10, 0, 0, 231, 32, 10, 0, 0, 230, 32, 10, 0, 0, 229, 32, 10, 0, 0, 228, 32, 10, 0, 0, 227, 32, 10, 0, 0, 226, 32, 10, 0, 0, 225, + 32, 10, 0, 0, 224, 32, 10, 0, 0, 223, 32, 10, 0, 0, 222, 32, 10, 0, 0, 221, 32, 10, 0, 0, 220, 32, 10, 0, 0, 219, 32, 10, 0, 0, 218, + 32, 10, 0, 0, 217, 32, 10, 0, 0, 216, 32, 10, 0, 0, 215, 32, 10, 0, 0, 214, 32, 10, 0, 0, 213, 32, 10, 0, 0, 212, 32, 10, 0, 0, 211, + 32, 10, 0, 0, 210, 32, 10, 0, 0, 209, 32, 10, 0, 0, 208, 32, 10, 0, 0, 207, 32, 10, 0, 0, 206, 32, 10, 0, 0, 205, 32, 10, 0, 0, 204, + 32, 10, 0, 0, 203, 32, 10, 0, 0, 202, 32, 10, 0, 0, 201, 32, 10, 0, 0, 200, 32, 10, 0, 0, 199, 32, 10, 0, 0, 198, 32, 10, 0, 0, 197, + 32, 10, 0, 0, 196, 32, 10, 0, 0, 195, 32, 10, 0, 0, 194, 32, 10, 0, 0, 193, 32, 10, 0, 0, 192, 32, 10, 0, 0, 191, 32, 10, 0, 0, 190, + 32, 10, 0, 0, 189, 32, 10, 0, 0, 188, 32, 10, 0, 0, 187, 32, 10, 0, 0, 186, 32, 10, 0, 0, 185, 32, 10, 0, 0, 184, 32, 10, 0, 0, 183, + 32, 10, 0, 0, 182, 32, 10, 0, 0, 181, 32, 10, 0, 0, 180, 32, 10, 0, 0, 179, 32, 10, 0, 0, 178, 32, 10, 0, 0, 177, 32, 10, 0, 0, 176, + 32, 10, 0, 0, 175, 32, 10, 0, 0, 174, 32, 10, 0, 0, 173, 32, 10, 0, 0, 172, 32, 10, 0, 0, 171, 32, 10, 0, 0, 170, 32, 10, 0, 0, 169, + 32, 10, 0, 0, 168, 32, 10, 0, 0, 167, 32, 10, 0, 0, 166, 32, 10, 0, 0, 165, 32, 10, 0, 0, 164, 32, 10, 0, 0, 163, 32, 10, 0, 0, 162, + 32, 10, 0, 0, 161, 32, 10, 0, 0, 160, 32, 10, 0, 0, 159, 32, 10, 0, 0, 158, 32, 10, 0, 0, 157, 32, 10, 0, 0, 156, 32, 10, 0, 0, 155, + 32, 10, 0, 0, 154, 32, 10, 0, 0, 153, 32, 10, 0, 0, 152, 32, 10, 0, 0, 151, 32, 10, 0, 0, 150, 32, 10, 0, 0, 149, 32, 10, 0, 0, 148, + 32, 10, 0, 0, 147, 32, 10, 0, 0, 146, 32, 10, 0, 0, 145, 32, 10, 0, 0, 144, 32, 10, 0, 0, 143, 32, 10, 0, 0, 142, 32, 10, 0, 0, 141, + 32, 10, 0, 0, 140, 32, 10, 0, 0, 139, 32, 10, 0, 0, 138, 32, 10, 0, 0, 137, 32, 10, 0, 0, 136, 32, 10, 0, 0, 135, 32, 10, 0, 0, 134, + 32, 10, 0, 0, 133, 32, 10, 0, 0, 132, 32, 10, 0, 0, 131, 32, 10, 0, 0, 130, 32, 10, 0, 0, 129, 32, 10, 0, 0, 128, 32, 10, 0, 0, 127, + 32, 10, 0, 0, 126, 32, 10, 0, 0, 125, 32, 10, 0, 0, 124, 32, 10, 0, 0, 123, 32, 10, 0, 0, 122, 32, 10, 0, 0, 121, 32, 10, 0, 0, 120, + 32, 10, 0, 0, 119, 32, 10, 0, 0, 118, 32, 10, 0, 0, 117, 32, 10, 0, 0, 116, 32, 10, 0, 0, 115, 32, 10, 0, 0, 114, 32, 10, 0, 0, 113, + 32, 10, 0, 0, 112, 32, 10, 0, 0, 111, 32, 10, 0, 0, 110, 32, 10, 0, 0, 109, 32, 10, 0, 0, 108, 32, 10, 0, 0, 107, 32, 10, 0, 0, 106, + 32, 10, 0, 0, 105, 32, 10, 0, 0, 104, 32, 10, 0, 0, 103, 32, 10, 0, 0, 102, 32, 10, 0, 0, 101, 32, 10, 0, 0, 100, 32, 10, 0, 0, 99, + 32, 10, 0, 0, 98, 32, 10, 0, 0, 97, 32, 10, 0, 0, 96, 32, 10, 0, 0, 95, 32, 10, 0, 0, 94, 32, 10, 0, 0, 93, 32, 10, 0, 0, 92, + 32, 10, 0, 0, 91, 32, 10, 0, 0, 90, 32, 10, 0, 0, 89, 32, 10, 0, 0, 88, 32, 10, 0, 0, 87, 32, 10, 0, 0, 86, 32, 10, 0, 0, 85, + 32, 10, 0, 0, 84, 32, 10, 0, 0, 83, 32, 10, 0, 0, 82, 32, 10, 0, 0, 81, 32, 10, 0, 0, 80, 32, 10, 0, 0, 79, 32, 10, 0, 0, 78, + 32, 10, 0, 0, 77, 32, 10, 0, 0, 76, 32, 10, 0, 0, 75, 32, 10, 0, 0, 74, 32, 10, 0, 0, 73, 32, 10, 0, 0, 72, 32, 10, 0, 0, 71, + 32, 10, 0, 0, 70, 32, 10, 0, 0, 69, 32, 10, 0, 0, 68, 32, 10, 0, 0, 67, 32, 10, 0, 0, 66, 32, 10, 0, 0, 65, 32, 10, 0, 0, 64, + 32, 10, 0, 0, 63, 32, 10, 0, 0, 62, 32, 10, 0, 0, 61, 32, 10, 0, 0, 60, 32, 10, 0, 0, 59, 32, 10, 0, 0, 58, 32, 10, 0, 0, 57, + 32, 10, 0, 0, 56, 32, 10, 0, 0, 55, 32, 10, 0, 0, 54, 32, 10, 0, 0, 53, 32, 10, 0, 0, 52, 32, 10, 0, 0, 51, 32, 10, 0, 0, 50, + 32, 10, 0, 0, 49, 32, 10, 0, 0, 48, 32, 10, 0, 0, 47, 32, 10, 0, 0, 46, 32, 10, 0, 0, 45, 32, 10, 0, 0, 44, 32, 10, 0, 0, 43, + 32, 10, 0, 0, 42, 32, 10, 0, 0, 41, 32, 10, 0, 0, 40, 32, 10, 0, 0, 39, 32, 10, 0, 0, 38, 32, 10, 0, 0, 37, 32, 10, 0, 0, 36, + 32, 10, 0, 0, 35, 32, 10, 0, 0, 34, 32, 10, 0, 0, 33, 32, 10, 0, 0, 32, 32, 10, 0, 0, 31, 32, 10, 0, 0, 30, 32, 10, 0, 0, 29, + 32, 10, 0, 0, 28, 32, 10, 0, 0, 27, 32, 10, 0, 0, 26, 32, 10, 0, 0, 25, 32, 10, 0, 0, 24, 32, 10, 0, 0, 23, 32, 10, 0, 0, 22, + 32, 10, 0, 0, 21, 32, 10, 0, 0, 20, 32, 10, 0, 0, 19, 32, 10, 0, 0, 18, 32, 10, 0, 0, 17, 32, 10, 0, 0, 16, 32, 10, 0, 0, 15, + 32, 10, 0, 0, 14, 32, 10, 0, 0, 13, 32, 10, 0, 0, 12, 32, 10, 0, 0, 11, 32, 10, 0, 0, 10, 32, 10, 0, 0, 9, 32, 10, 0, 0, 8, + 32, 10, 0, 0, 7, 32, 10, 0, 0, 6, 32, 10, 0, 0, 5, 32, 10, 0, 0, 4, 32, 10, 0, 0, 3, 32, 10, 0, 0, 2, 32, 10, 0, 0, 1, 32, 10, 0, 0, 0, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 3, 241, + 2, 0, 0, 0, 21, + 64, 2, 0, 64, 1, 1, 0, 64, 3, 4, 0, 0, 0, 0, 64, 5, 4, 0, 0, 0, 100, + 32, 10, 0, 3, 228, 32, 10, 0, 3, 227, 32, 10, 0, 3, 226, 32, 10, 0, 3, 225, 32, 10, 0, 3, 224, 32, 10, 0, 3, 223, 32, 10, 0, 3, 222, + 32, 10, 0, 3, 221, 32, 10, 0, 3, 220, 32, 10, 0, 3, 219, 32, 10, 0, 3, 218, 32, 10, 0, 3, 217, 32, 10, 0, 3, 216, 32, 10, 0, 3, 215, + 32, 10, 0, 3, 214, 32, 10, 0, 3, 213, 32, 10, 0, 3, 212, 32, 10, 0, 3, 211, 32, 10, 0, 3, 210, 32, 10, 0, 3, 209, 32, 10, 0, 3, 208, + 32, 10, 0, 3, 207, 32, 10, 0, 3, 206, 32, 10, 0, 3, 205, 32, 10, 0, 3, 204, 32, 10, 0, 3, 203, 32, 10, 0, 3, 202, 32, 10, 0, 3, 201, + 32, 10, 0, 3, 200, 32, 10, 0, 3, 199, 32, 10, 0, 3, 198, 32, 10, 0, 3, 197, 32, 10, 0, 3, 196, 32, 10, 0, 3, 195, 32, 10, 0, 3, 194, + 32, 10, 0, 3, 193, 32, 10, 0, 3, 192, 32, 10, 0, 3, 191, 32, 10, 0, 3, 190, 32, 10, 0, 3, 189, 32, 10, 0, 3, 188, 32, 10, 0, 3, 187, + 32, 10, 0, 3, 186, 32, 10, 0, 3, 185, 32, 10, 0, 3, 184, 32, 10, 0, 3, 183, 32, 10, 0, 3, 182, 32, 10, 0, 3, 181, 32, 10, 0, 3, 180, + 32, 10, 0, 3, 179, 32, 10, 0, 3, 178, 32, 10, 0, 3, 177, 32, 10, 0, 3, 176, 32, 10, 0, 3, 175, 32, 10, 0, 3, 174, 32, 10, 0, 3, 173, + 32, 10, 0, 3, 172, 32, 10, 0, 3, 171, 32, 10, 0, 3, 170, 32, 10, 0, 3, 169, 32, 10, 0, 3, 168, 32, 10, 0, 3, 167, 32, 10, 0, 3, 166, + 32, 10, 0, 3, 165, 32, 10, 0, 3, 164, 32, 10, 0, 3, 163, 32, 10, 0, 3, 162, 32, 10, 0, 3, 161, 32, 10, 0, 3, 160, 32, 10, 0, 3, 159, + 32, 10, 0, 3, 158, 32, 10, 0, 3, 157, 32, 10, 0, 3, 156, 32, 10, 0, 3, 155, 32, 10, 0, 3, 154, 32, 10, 0, 3, 153, 32, 10, 0, 3, 152, + 32, 10, 0, 3, 151, 32, 10, 0, 3, 150, 32, 10, 0, 3, 149, 32, 10, 0, 3, 148, 32, 10, 0, 3, 147, 32, 10, 0, 3, 146, 32, 10, 0, 3, 145, + 32, 10, 0, 3, 144, 32, 10, 0, 3, 143, 32, 10, 0, 3, 142, 32, 10, 0, 3, 141, 32, 10, 0, 3, 140, 32, 10, 0, 3, 139, 32, 10, 0, 3, 138, + 32, 10, 0, 3, 137, 32, 10, 0, 3, 136, 32, 10, 0, 3, 135, 32, 10, 0, 3, 134, 32, 10, 0, 3, 133, 32, 10, 0, 3, 132, 32, 10, 0, 3, 131, + 32, 10, 0, 3, 130, 32, 10, 0, 3, 129, 32, 10, 0, 3, 128, 32, 10, 0, 3, 127, 32, 10, 0, 3, 126, 32, 10, 0, 3, 125, 32, 10, 0, 3, 124, + 32, 10, 0, 3, 123, 32, 10, 0, 3, 122, 32, 10, 0, 3, 121, 32, 10, 0, 3, 120, 32, 10, 0, 3, 119, 32, 10, 0, 3, 118, 32, 10, 0, 3, 117, + 32, 10, 0, 3, 116, 32, 10, 0, 3, 115, 32, 10, 0, 3, 114, 32, 10, 0, 3, 113, 32, 10, 0, 3, 112, 32, 10, 0, 3, 111, 32, 10, 0, 3, 110, + 32, 10, 0, 3, 109, 32, 10, 0, 3, 108, 32, 10, 0, 3, 107, 32, 10, 0, 3, 106, 32, 10, 0, 3, 105, 32, 10, 0, 3, 104, 32, 10, 0, 3, 103, + 32, 10, 0, 3, 102, 32, 10, 0, 3, 101, 32, 10, 0, 3, 100, 32, 10, 0, 3, 99, 32, 10, 0, 3, 98, 32, 10, 0, 3, 97, 32, 10, 0, 3, 96, + 32, 10, 0, 3, 95, 32, 10, 0, 3, 94, 32, 10, 0, 3, 93, 32, 10, 0, 3, 92, 32, 10, 0, 3, 91, 32, 10, 0, 3, 90, 32, 10, 0, 3, 89, + 32, 10, 0, 3, 88, 32, 10, 0, 3, 87, 32, 10, 0, 3, 86, 32, 10, 0, 3, 85, 32, 10, 0, 3, 84, 32, 10, 0, 3, 83, 32, 10, 0, 3, 82, + 32, 10, 0, 3, 81, 32, 10, 0, 3, 80, 32, 10, 0, 3, 79, 32, 10, 0, 3, 78, 32, 10, 0, 3, 77, 32, 10, 0, 3, 76, 32, 10, 0, 3, 75, + 32, 10, 0, 3, 74, 32, 10, 0, 3, 73, 32, 10, 0, 3, 72, 32, 10, 0, 3, 71, 32, 10, 0, 3, 70, 32, 10, 0, 3, 69, 32, 10, 0, 3, 68, + 32, 10, 0, 3, 67, 32, 10, 0, 3, 66, 32, 10, 0, 3, 65, 32, 10, 0, 3, 64, 32, 10, 0, 3, 63, 32, 10, 0, 3, 62, 32, 10, 0, 3, 61, + 32, 10, 0, 3, 60, 32, 10, 0, 3, 59, 32, 10, 0, 3, 58, 32, 10, 0, 3, 57, 32, 10, 0, 3, 56, 32, 10, 0, 3, 55, 32, 10, 0, 3, 54, + 32, 10, 0, 3, 53, 32, 10, 0, 3, 52, 32, 10, 0, 3, 51, 32, 10, 0, 3, 50, 32, 10, 0, 3, 49, 32, 10, 0, 3, 48, 32, 10, 0, 3, 47, + 32, 10, 0, 3, 46, 32, 10, 0, 3, 45, 32, 10, 0, 3, 44, 32, 10, 0, 3, 43, 32, 10, 0, 3, 42, 32, 10, 0, 3, 41, 32, 10, 0, 3, 40, + 32, 10, 0, 3, 39, 32, 10, 0, 3, 38, 32, 10, 0, 3, 37, 32, 10, 0, 3, 36, + }, + }, + }, + } + + for _, test := range tests { + fsmA := newFSM2(&peer{ + addr: net.ParseIP("169.254.100.100"), + rib: locRIB.New(), + importFilter: filter.NewAcceptAllFilter(), + exportFilter: filter.NewAcceptAllFilter(), + }) + + fsmA.holdTimer = time.NewTimer(time.Second * 90) + fsmA.keepaliveTimer = time.NewTimer(time.Second * 30) + fsmA.connectRetryTimer = time.NewTimer(time.Second * 120) + fsmA.state = newEstablishedState(fsmA) + fsmA.con = btest.NewMockConn() + + if test.addPath { + fsmA.options = &types.Options{ + AddPathRX: true, + } + } + + updateSender := newUpdateSender(fsmA) + + for _, pathPfx := range test.paths { + for _, pfx := range pathPfx.pfxs { + updateSender.AddPath(pfx, pathPfx.path) + } + if test.generateNLRIs != 0 { + for i := uint64(0); i < test.generateNLRIs; i++ { + x := i / 256 + y := i - x + pfx := bnet.NewPfx(bnet.IPv4ToUint32(net.IP([]byte{10, 0, uint8(x), uint8(y)})), 32) + updateSender.AddPath(pfx, pathPfx.path) + } + } + } + + updateSender.Start(time.Millisecond) + time.Sleep(time.Millisecond * 100) + + recvBuffer := make([]byte, 8192) + nbytes, _ := fsmA.con.Read(recvBuffer) + + if len(test.expectedUpdates) == 1 { + assert.Equal(t, test.expectedUpdates[0], recvBuffer[:nbytes]) + } else { + ok := false + for _, updateSequence := range test.expectedUpdates { + if reflect.DeepEqual(recvBuffer[:nbytes], updateSequence) { + ok = true + break + } + } + + if !ok { + t.Errorf("Expected update for test %q not found: Want: %v Got: %v", test.name, test.expectedUpdates, recvBuffer[:nbytes]) + } + } + } +} diff --git a/testing/conn_mock.go b/testing/conn_mock.go index 86e8e1ae7d1c91eaa6efce317d34e8b08212c825..2db28011a5d3080d28b1c24cde9895ebee496cd1 100644 --- a/testing/conn_mock.go +++ b/testing/conn_mock.go @@ -1,6 +1,8 @@ package testing -import "net" +import ( + "net" +) // MockConn mock an connection type MockConn struct { @@ -27,6 +29,6 @@ func (m *MockConn) Read(b []byte) (n int, err error) { count = len(m.Bytes) } - copy(m.Bytes[0:count], b) + copy(b, m.Bytes[0:count]) return count, nil }