From 00d761c3d4e40b0c2180d044cf721cae43724358 Mon Sep 17 00:00:00 2001 From: Paul Lorenz Date: Tue, 3 Sep 2024 14:45:51 -0400 Subject: [PATCH] Add low overhead payload protocol. Fixes #2427 --- common/inspect/circuit_inspections.go | 2 +- router/handler_link/bind.go | 4 + router/xgress/heartbeat_transformer.go | 38 + router/xgress/link_send_buffer.go | 68 +- router/xgress/messages.go | 17 + router/xgress/minimal_payload_test.go | 372 ++ router/xgress/xgress.go | 289 +- router/xgress_common/connection.go | 6 +- router/xlink_transport/dialer.go | 3 + router/xlink_transport/listener.go | 2 + .../models/dtls-west/actions/bootstrap.go | 130 + zititest/models/dtls-west/actions/start.go | 50 + .../models/dtls-west/configs/ctrl.yml.tmpl | 196 + .../models/dtls-west/configs/router.yml.tmpl | 110 + zititest/models/dtls-west/main.go | 225 + zititest/models/dtls/FlowControl.json | 3934 +++++++++++++++++ zititest/models/dtls/configs/router.yml.tmpl | 31 +- zititest/models/dtls/main.go | 22 +- 18 files changed, 5436 insertions(+), 63 deletions(-) create mode 100644 router/xgress/heartbeat_transformer.go create mode 100644 router/xgress/minimal_payload_test.go create mode 100644 zititest/models/dtls-west/actions/bootstrap.go create mode 100644 zititest/models/dtls-west/actions/start.go create mode 100644 zititest/models/dtls-west/configs/ctrl.yml.tmpl create mode 100644 zititest/models/dtls-west/configs/router.yml.tmpl create mode 100644 zititest/models/dtls-west/main.go create mode 100644 zititest/models/dtls/FlowControl.json diff --git a/common/inspect/circuit_inspections.go b/common/inspect/circuit_inspections.go index 437440786..7e8606027 100644 --- a/common/inspect/circuit_inspections.go +++ b/common/inspect/circuit_inspections.go @@ -41,7 +41,7 @@ type XgressDetail struct { XgressPointer string `json:"xgressPointer"` LinkSendBufferPointer string `json:"linkSendBufferPointer"` Goroutines []string `json:"goroutines"` - Sequence int32 `json:"sequence"` + Sequence uint64 `json:"sequence"` Flags string `json:"flags"` } diff --git a/router/handler_link/bind.go b/router/handler_link/bind.go index d38dac346..da7af4ceb 100644 --- a/router/handler_link/bind.go +++ b/router/handler_link/bind.go @@ -13,6 +13,7 @@ import ( "github.com/openziti/ziti/router/env" "github.com/openziti/ziti/router/forwarder" metrics2 "github.com/openziti/ziti/router/metrics" + "github.com/openziti/ziti/router/xgress" "github.com/openziti/ziti/router/xlink" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -79,6 +80,9 @@ func (self *bindHandler) BindChannel(binding channel.Binding) error { binding.AddTypedReceiveHandler(newControlHandler(self.xlink, self.forwarder)) binding.AddPeekHandler(metrics2.NewChannelPeekHandler(self.xlink.Id(), self.forwarder.MetricsRegistry())) binding.AddPeekHandler(trace.NewChannelPeekHandler(self.xlink.Id(), ch, self.forwarder.TraceController())) + if self.xlink.LinkProtocol() == "dtls" { + binding.AddTransformHandler(xgress.PayloadTransformer{}) + } if err := self.xlink.Init(self.forwarder.MetricsRegistry()); err != nil { return err } diff --git a/router/xgress/heartbeat_transformer.go b/router/xgress/heartbeat_transformer.go new file mode 100644 index 000000000..85eea5e7d --- /dev/null +++ b/router/xgress/heartbeat_transformer.go @@ -0,0 +1,38 @@ +/* + Copyright NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "encoding/binary" + "github.com/openziti/channel/v3" + "time" +) + +type PayloadTransformer struct { +} + +func (self PayloadTransformer) Rx(*channel.Message, channel.Channel) {} + +func (self PayloadTransformer) Tx(m *channel.Message, ch channel.Channel) { + if m.ContentType == channel.ContentTypeRaw && len(m.Body) > 1 { + if m.Body[0]&HeartbeatFlagMask != 0 && len(m.Body) > 12 { + now := time.Now().UnixNano() + m.PutUint64Header(channel.HeartbeatHeader, uint64(now)) + binary.BigEndian.PutUint64(m.Body[len(m.Body)-8:], uint64(now)) + } + } +} diff --git a/router/xgress/link_send_buffer.go b/router/xgress/link_send_buffer.go index ba768cbd6..6fa8e0b74 100644 --- a/router/xgress/link_send_buffer.go +++ b/router/xgress/link_send_buffer.go @@ -23,6 +23,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "math" + "slices" "sync/atomic" "time" ) @@ -161,7 +162,7 @@ func (buffer *LinkSendBuffer) Close() { func (buffer *LinkSendBuffer) isBlocked() bool { blocked := false - if buffer.windowsSize < buffer.linkRecvBufferSize { + if buffer.x.Options.TxPortalMaxSize < buffer.linkRecvBufferSize { blocked = true if !buffer.blockedByRemoteWindow { buffer.blockedByRemoteWindow = true @@ -202,17 +203,13 @@ func (buffer *LinkSendBuffer) run() { for { // bias acks, process all pending, since that should not block - processingAcks := true - for processingAcks { - select { - case ack := <-buffer.newlyReceivedAcks: - buffer.receiveAcknowledgement(ack) - case <-buffer.closeNotify: - buffer.close() - return - default: - processingAcks = false - } + select { + case ack := <-buffer.newlyReceivedAcks: + buffer.receiveAcknowledgement(ack) + case <-buffer.closeNotify: + buffer.close() + return + default: } // don't block when we're closing, since the only thing that should still be coming in is end-of-circuit @@ -221,6 +218,21 @@ func (buffer *LinkSendBuffer) run() { buffered = nil } else { buffered = buffer.newlyBuffered + + select { + case txPayload := <-buffered: + buffer.buffer[txPayload.payload.GetSequence()] = txPayload + payloadSize := len(txPayload.payload.Data) + buffer.linkSendBufferSize += uint32(payloadSize) + atomic.AddInt64(&outstandingPayloads, 1) + atomic.AddInt64(&outstandingPayloadBytes, int64(payloadSize)) + log.Tracef("buffering payload %v with size %v. payload buffer size: %v", + txPayload.payload.Sequence, len(txPayload.payload.Data), buffer.linkSendBufferSize) + case <-buffer.closeNotify: + buffer.close() + return + default: + } } select { @@ -288,7 +300,7 @@ func (buffer *LinkSendBuffer) receiveAcknowledgement(ack *Acknowledgement) { if buffer.windowsSize > buffer.x.Options.TxPortalMaxSize { buffer.windowsSize = buffer.x.Options.TxPortalMaxSize } - buffer.retxScale -= 0.02 + buffer.retxScale -= 0.01 if buffer.retxScale < buffer.x.Options.RetxScale { buffer.retxScale = buffer.x.Options.RetxScale } @@ -320,17 +332,27 @@ func (buffer *LinkSendBuffer) retransmit() { log := pfxlog.ContextLogger(buffer.x.Label()) retransmitted := 0 + var rtxList []*txPayload for _, v := range buffer.buffer { - if v.isRetransmittable() && uint32(now-v.getAge()) >= buffer.retxThreshold { - v.markQueued() - retransmitter.queue(v) - retransmitted++ - buffer.retransmits++ - if buffer.retransmits >= buffer.x.Options.TxPortalRetxThresh { - buffer.accumulator = 0 - buffer.retransmits = 0 - buffer.scale(buffer.x.Options.TxPortalRetxScale) - } + age := v.getAge() + if age != math.MaxInt64 && v.isRetransmittable() && uint32(now-age) >= buffer.retxThreshold { + rtxList = append(rtxList, v) + } + } + + slices.SortFunc(rtxList, func(a, b *txPayload) int { + return int(a.payload.Sequence - b.payload.Sequence) + }) + + for _, v := range rtxList { + v.markQueued() + retransmitter.queue(v) + retransmitted++ + buffer.retransmits++ + if buffer.retransmits >= buffer.x.Options.TxPortalRetxThresh { + buffer.accumulator = 0 + buffer.retransmits = 0 + buffer.scale(buffer.x.Options.TxPortalRetxScale) } } diff --git a/router/xgress/messages.go b/router/xgress/messages.go index 8a2f6111a..c561558d0 100644 --- a/router/xgress/messages.go +++ b/router/xgress/messages.go @@ -36,6 +36,7 @@ const ( HeaderKeyFlags = 2258 HeaderKeyRecvBufferSize = 2259 HeaderKeyRTT = 2260 + HeaderPayloadRaw = 2261 ContentTypePayloadType = 1100 ContentTypeAcknowledgementType = 1101 @@ -197,6 +198,7 @@ type Payload struct { Sequence int32 Headers map[uint8][]byte Data []byte + raw []byte } func (payload *Payload) GetSequence() int32 { @@ -204,6 +206,17 @@ func (payload *Payload) GetSequence() int32 { } func (payload *Payload) Marshall() *channel.Message { + if payload.raw != nil { + if payload.raw[0]&RttFlagMask != 0 { + rtt := uint16(info.NowInMilliseconds()) + b0 := byte(rtt) + b1 := byte(rtt >> 8) + payload.raw[2] = b0 + payload.raw[3] = b1 + } + return channel.NewMessage(channel.ContentTypeRaw, payload.raw) + } + msg := channel.NewMessage(ContentTypePayloadType, payload.Data) addPayloadHeadersToMsg(msg, payload.Headers) msg.Headers[HeaderKeyCircuitId] = []byte(payload.CircuitId) @@ -260,6 +273,10 @@ func UnmarshallPayload(msg *channel.Message) (*Payload, error) { } payload.Sequence = int32(sequence) + if raw, ok := msg.Headers[HeaderPayloadRaw]; ok { + payload.raw = raw + } + return payload, nil } diff --git a/router/xgress/minimal_payload_test.go b/router/xgress/minimal_payload_test.go new file mode 100644 index 000000000..4143f86ff --- /dev/null +++ b/router/xgress/minimal_payload_test.go @@ -0,0 +1,372 @@ +package xgress + +import ( + "encoding/binary" + "errors" + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/channel/v3" + "github.com/openziti/metrics" + "github.com/openziti/ziti/controller/idgen" + cmap "github.com/orcaman/concurrent-map/v2" + metrics2 "github.com/rcrowley/go-metrics" + "github.com/sirupsen/logrus" + "io" + "testing" + "time" +) + +func newTestXgConn(bufferSize int, targetSends uint32, targetReceives uint32) *testXgConn { + return &testXgConn{ + bufferSize: bufferSize, + targetSends: targetSends, + targetReceives: targetReceives, + done: make(chan struct{}), + errs: make(chan error, 1), + } +} + +type testXgConn struct { + sndMsgCounter uint32 + rcvMsgCounter uint32 + bufferSize int + targetSends uint32 + targetReceives uint32 + sendCounter uint32 + recvCounter uint32 + done chan struct{} + errs chan error + bufCounter uint32 +} + +func (self *testXgConn) Close() error { + return nil +} + +func (self *testXgConn) LogContext() string { + return "test" +} + +func (self *testXgConn) ReadPayload() ([]byte, map[uint8][]byte, error) { + self.sndMsgCounter++ + if self.targetSends == 0 { + time.Sleep(time.Minute) + } + var m map[uint8][]byte + buf := make([]byte, self.bufferSize) + sl := buf + for len(sl) > 0 && self.sendCounter < self.targetSends { + binary.BigEndian.PutUint32(sl, self.sendCounter) + self.sendCounter++ + sl = sl[4:] + } + + if len(sl) > 0 { + buf = buf[:len(buf)-len(sl)] + } + + if self.sndMsgCounter%10 == 0 { + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, self.sndMsgCounter) + m = map[uint8][]byte{ + 5: b, + } + if self.sndMsgCounter%20 == 0 { + m[10] = []byte("hello") + } + } + + if self.sendCounter >= self.targetSends { + //fmt.Printf("sending final %d bytes\n", len(buf)) + return buf, nil, io.EOF + } + + //fmt.Printf("sending %d bytes\n", len(buf)) + + return buf, m, nil +} + +func (self *testXgConn) WritePayload(buf []byte, m map[uint8][]byte) (int, error) { + self.rcvMsgCounter++ + sl := buf + for len(sl) > 0 { + next := binary.BigEndian.Uint32(sl) + sl = sl[4:] + if next != self.recvCounter { + select { + case self.errs <- fmt.Errorf("expected counter %d, got %d, buf: %d", self.recvCounter, next, self.bufCounter): + default: + } + } + self.recvCounter++ + if self.recvCounter == self.targetReceives { + close(self.done) + } else if self.recvCounter > self.targetReceives { + select { + case self.errs <- fmt.Errorf("exceeded expected counter %d, got %d, buf: %d", self.targetReceives, self.recvCounter, self.bufCounter): + default: + } + } + } + + if self.rcvMsgCounter%10 == 0 { + b, ok := m[5] + if !ok { + select { + case self.errs <- fmt.Errorf("expected header 5, got %+v headers, rcv count: %d", m, self.rcvMsgCounter): + default: + } + } else if len(b) != 4 { + select { + case self.errs <- fmt.Errorf("expected header 5, len 4, got %+v, rcv count: %d", b, self.rcvMsgCounter): + default: + } + } else { + v := binary.BigEndian.Uint32(b) + if v != self.rcvMsgCounter { + select { + case self.errs <- fmt.Errorf("expected header counter %d, got %d", self.rcvMsgCounter, v): + default: + } + } + } + if self.rcvMsgCounter%20 == 0 { + if string(m[10]) != "hello" { + select { + case self.errs <- fmt.Errorf("missing 10:hello in map, counter %d", self.recvCounter): + default: + } + } + } + } + + //fmt.Printf("received %d bytes\n", len(buf)) + self.bufCounter++ + + return len(buf), nil +} + +func (self *testXgConn) HandleControlMsg(controlType ControlType, headers channel.Headers, responder ControlReceiver) error { + panic("implement me") +} + +type testIntermediary struct { + circuitId string + dest *Xgress + msgs channel.MessageStrategy + payloadTransformer PayloadTransformer + counter uint64 + bytesCallback func([]byte) +} + +func (self *testIntermediary) HandleXgressReceive(payload *Payload, x *Xgress) { + m := payload.Marshall() + self.payloadTransformer.Tx(m, nil) + b, err := self.msgs.GetMarshaller()(m) + if err != nil { + panic(err) + } + + if self.bytesCallback != nil { + self.bytesCallback(b) + } + + m, err = self.msgs.GetPacketProducer()(b) + if err != nil { + logrus.WithError(err).Error("error get next msg") + panic(err) + } + + if err = self.validateMessage(m); err != nil { + panic(err) + } + + payload, err = UnmarshallPayload(m) + if err != nil { + panic(err) + } + + if err = self.dest.SendPayload(payload, 0, PayloadTypeXg); err != nil { + panic(err) + } + //fmt.Printf("transmitted payload %d from %s -> %s\n", payload.Sequence, x.address, self.dest.address) +} + +func (self *testIntermediary) validateMessage(m *channel.Message) error { + circuitId, found := m.GetStringHeader(HeaderKeyCircuitId) + if !found { + return errors.New("no circuit id found") + } + + if circuitId != self.circuitId { + return fmt.Errorf("expected circuit id %s, got %s", self.circuitId, circuitId) + } + + seq, found := m.GetUint64Header(HeaderKeySequence) + if !found { + return errors.New("no sequence found") + } + if seq != self.counter { + return fmt.Errorf("expected sequence %d, got %d", self.counter, seq) + } + self.counter++ + + return nil +} + +func (self *testIntermediary) HandleControlReceive(control *Control, x *Xgress) { + panic("implement me") +} + +type testAcker struct { + destinations cmap.ConcurrentMap[string, *Xgress] +} + +func (self *testAcker) ack(ack *Acknowledgement, address Address) { + dest, _ := self.destinations.Get(string(address)) + if dest != nil { + if err := dest.SendAcknowledgement(ack); err != nil { + panic(err) + } + } else { + panic(fmt.Errorf("no xgress found with id %s", string(address))) + } +} + +type mockForwarder struct{} + +func (m mockForwarder) RetransmitPayload(srcAddr Address, payload *Payload) error { + return nil +} + +func (m mockForwarder) ForwardAcknowledgement(srcAddr Address, acknowledgement *Acknowledgement) error { + return nil +} + +type mockFaulter struct{} + +func (m mockFaulter) ReportForwardingFault(circuitId string, ctrlId string) { +} + +func Test_MinimalPayloadMarshalling(t *testing.T) { + logOptions := pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").NoColor() + pfxlog.GlobalInit(logrus.InfoLevel, logOptions) + pfxlog.SetFormatter(pfxlog.NewFormatter(pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").StartingToday())) + + metricsRegistry := metrics.NewRegistry("test", nil) + InitMetrics(metricsRegistry) + + closeNotify := make(chan struct{}) + defer func() { + close(closeNotify) + }() + + InitPayloadIngester(closeNotify) + InitRetransmitter(mockForwarder{}, mockFaulter{}, metricsRegistry, closeNotify) + + ackHandler := &testAcker{ + destinations: cmap.New[*Xgress](), + } + acker = ackHandler + options := DefaultOptions() + options.Mtu = 1400 + + circuitId := idgen.New() + srcTestConn := newTestXgConn(10_000, 100_000, 0) + dstTestConn := newTestXgConn(10_000, 0, 100_000) + + srcXg := NewXgress(circuitId, "ctrl", "src", srcTestConn, Initiator, options, nil) + dstXg := NewXgress(circuitId, "ctrl", "dst", dstTestConn, Terminator, options, nil) + + ackHandler.destinations.Set("src", dstXg) + ackHandler.destinations.Set("dst", srcXg) + + msgStrategy := channel.DatagramMessageStrategy(UnmarshallPacketPayload) + srcXg.receiveHandler = &testIntermediary{ + circuitId: circuitId, + dest: dstXg, + msgs: msgStrategy, + } + + dstXg.receiveHandler = &testIntermediary{ + circuitId: circuitId, + dest: srcXg, + msgs: msgStrategy, + } + + srcXg.Start() + dstXg.Start() + + select { + case <-dstTestConn.done: + case err := <-dstTestConn.errs: + t.Fatal(err) + case <-time.After(time.Second): + t.Fatal("timeout") + } +} + +func Test_PayloadSize(t *testing.T) { + logOptions := pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").NoColor() + pfxlog.GlobalInit(logrus.InfoLevel, logOptions) + pfxlog.SetFormatter(pfxlog.NewFormatter(pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").StartingToday())) + + metricsRegistry := metrics.NewRegistry("test", nil) + InitMetrics(metricsRegistry) + + closeNotify := make(chan struct{}) + defer func() { + close(closeNotify) + }() + + InitPayloadIngester(closeNotify) + InitRetransmitter(mockForwarder{}, mockFaulter{}, metricsRegistry, closeNotify) + + ackHandler := &testAcker{ + destinations: cmap.New[*Xgress](), + } + acker = ackHandler + options := DefaultOptions() + //options.Mtu = 1435 + + h := metricsRegistry.Histogram("msg_size") + + circuitId := idgen.New() + srcTestConn := newTestXgConn(200, 100_000, 0) + dstTestConn := newTestXgConn(200, 0, 100_000) + + srcXg := NewXgress(circuitId, "ctrl", "src", srcTestConn, Initiator, options, nil) + dstXg := NewXgress(circuitId, "ctrl", "dst", dstTestConn, Terminator, options, nil) + + ackHandler.destinations.Set("src", dstXg) + ackHandler.destinations.Set("dst", srcXg) + + msgStrategy := channel.DatagramMessageStrategy(UnmarshallPacketPayload) + srcXg.receiveHandler = &testIntermediary{ + circuitId: circuitId, + dest: dstXg, + msgs: msgStrategy, + bytesCallback: func(bytes []byte) { + h.Update(int64(len(bytes))) + }, + } + + dstXg.receiveHandler = &testIntermediary{ + circuitId: circuitId, + dest: srcXg, + msgs: msgStrategy, + } + + srcXg.Start() + dstXg.Start() + + select { + case <-dstTestConn.done: + case err := <-dstTestConn.errs: + t.Fatal(err) + case <-time.After(time.Second): + t.Fatal("timeout") + } + + fmt.Printf("max msg size: %d\n", h.(metrics2.Histogram).Max()) +} diff --git a/router/xgress/xgress.go b/router/xgress/xgress.go index d948a7029..c509e2260 100644 --- a/router/xgress/xgress.go +++ b/router/xgress/xgress.go @@ -20,6 +20,7 @@ import ( "bufio" "bytes" "encoding/binary" + "errors" "fmt" "io" "math/rand" @@ -145,7 +146,7 @@ type Xgress struct { Options *Options txQueue chan *Payload closeNotify chan struct{} - rxSequence int32 + rxSequence uint64 rxSequenceLock sync.Mutex receiveHandler ReceiveHandler payloadBuffer *LinkSendBuffer @@ -266,7 +267,7 @@ func (self *Xgress) GetStartCircuit() *Payload { startCircuit := &Payload{ CircuitId: self.circuitId, Flags: SetOriginatorFlag(uint32(PayloadFlagCircuitStart), self.originator), - Sequence: self.nextReceiveSequence(), + Sequence: int32(self.nextReceiveSequence()), Data: nil, } return startCircuit @@ -276,7 +277,7 @@ func (self *Xgress) GetEndCircuit() *Payload { endCircuit := &Payload{ CircuitId: self.circuitId, Flags: SetOriginatorFlag(uint32(PayloadFlagCircuitEnd), self.originator), - Sequence: self.nextReceiveSequence(), + Sequence: int32(self.nextReceiveSequence()), Data: nil, } return endCircuit @@ -384,14 +385,11 @@ func (self *Xgress) HandleControlReceive(controlType ControlType, headers channe func (self *Xgress) payloadIngester(payload *Payload) { if payload.IsCircuitStartFlagSet() && self.firstCircuitStartReceived() { - pfxlog.ContextLogger(self.Label()).WithFields(payload.GetLoggerFields()).Debug("received circuit start, starting xgress receiver") go self.rx() } if !self.Options.RandomDrops || rand.Int31n(self.Options.Drop1InN) != 1 { self.PayloadReceived(payload) - } else { - pfxlog.ContextLogger(self.Label()).WithFields(payload.GetLoggerFields()).Error("drop!") } self.queueSends() } @@ -575,6 +573,64 @@ func (self *Xgress) flushSendThenClose() { }) } +/** + Payload format + + Field 1: 1 byte - version and flags + Masks + * 00000000 - Always 0 to indicate type. The standard channel header 4 byte protocol indicator has a 1 in bit 0 of the first byte + * 00000110 - Version, v0-v3. Assumption is that if we ever get to v4, we can roll back to 0, since everything + should have upgraded past v0 by that point + * 00001000 - Terminator Flag - indicates the payload origin, initiator (0) or terminator (1) + * 00010000 - RTT Flag. Indicates if the payload contains an RTT. We don't need to send RTT on every payload. + * 00100000 - Chunk Flag. Indicates if this payload is chunked. + * 01000000 - Headers flag. Indicates this payload contains headers. + * 10000000 - Heartbeat Flag. Indicates the payload contains a heartbeat + + Field 2: 1 byte, Circuit id size + Masks + * 00001111 - Number of bytes in circuit id. Supports circuit ids which take up to 15 bytes. + Circuits ids are currently at 9 bytes. + * 11110000 - currently unused + + Field 3: RTT (optional) + - 2 bytes + + Field 4: CircuitId + - direct bytes representation of string encoded circuit id + + Field 5: Sequence number + - Encoded using binary.PutUvarint + + Field 6: Headers + - Presence indicated by headers flag in first field + length - encoded with binary.PutUvarint + for each key/value pair - + key - 1 byte + value length - encoded with binary.PutUvarint + value - byte array, directly appended + + + Field 7: Data + + Field 8: Heartbeat + - 8 bytes + - only included if there's extra room +*/ + +const ( + VersionMask byte = 0b00000110 + TerminatorFlagMask byte = 0b00001000 + RttFlagMask byte = 0b00010000 + ChunkFlagMask byte = 0b00100000 + HeadersFlagMask byte = 0b01000000 + HeartbeatFlagMask byte = 0b10000000 + + CircuitIdSizeMask byte = 0b00001111 + PayloadProtocolV1 byte = 1 + PayloadProtocolOffset byte = 1 +) + func (self *Xgress) rx() { log := pfxlog.ContextLogger(self.Label()) @@ -610,7 +666,7 @@ func (self *Xgress) rx() { return } - if n < int(self.Options.Mtu) || self.Options.Mtu == 0 { + if self.Options.Mtu == 0 { if !self.sendUnchunkedBuffer(buffer, headers) { return } @@ -618,28 +674,91 @@ func (self *Xgress) rx() { } first := true - for len(buffer) > 0 { + chunked := false + for len(buffer) > 0 || (first && len(headers) > 0) { + seq := self.nextReceiveSequence() + chunk := make([]byte, self.Options.Mtu) - dataTarget := chunk - offset := 0 - if first { - offset = binary.PutUvarint(chunk, uint64(n)) - dataTarget = chunk[offset:] + + flagsHeader := VersionMask & (PayloadProtocolV1 << PayloadProtocolOffset) + var sizesHeader byte + if self.originator == Terminator { + flagsHeader |= TerminatorFlagMask + } + + written := 2 + rest := chunk[2:] + includeRtt := seq%5 == 0 + if includeRtt { + flagsHeader |= RttFlagMask + written += 2 + rest = rest[2:] + } + + size := copy(rest, self.circuitId) + sizesHeader |= CircuitIdSizeMask & uint8(size) + written += size + rest = rest[size:] + size = binary.PutUvarint(rest, seq) + rest = rest[size:] + written += size + + if first && len(headers) > 0 { + flagsHeader |= HeadersFlagMask + size, err = writeU8ToBytesMap(headers, rest) + if err != nil { + log.WithError(err).Error("payload encoding error, closing") + return + } + rest = rest[size:] + written += size } - written := copy(dataTarget, buffer) - buffer = buffer[written:] + data := rest + dataLen := 0 + if first && len(rest) < len(buffer) { + chunked = true + size = binary.PutUvarint(rest, uint64(n)) + dataLen += size + written += size + rest = rest[size:] + } + + if chunked { + flagsHeader |= ChunkFlagMask + } + + size = copy(rest, buffer) + written += size + dataLen += size + + buffer = buffer[size:] + + // check if there's room for a heartbeat + if written+8 <= len(chunk) { + flagsHeader |= HeartbeatFlagMask + written += 8 + } + + chunk[0] = flagsHeader + chunk[1] = sizesHeader payload := &Payload{ CircuitId: self.circuitId, - Flags: setPayloadFlag(SetOriginatorFlag(0, self.originator), PayloadFlagChunk), - Sequence: self.nextReceiveSequence(), - Data: chunk[:offset+written], + Flags: SetOriginatorFlag(0, self.originator), + Sequence: int32(seq), + Data: data[:dataLen], + raw: chunk[:written], + } + + if chunked { + payload.Flags = setPayloadFlag(payload.Flags, PayloadFlagChunk) } if first { payload.Headers = headers } + log.Debugf("sending payload chunk. seq: %d, first: %v, chunk size: %d, payload size: %d, remainder: %d", payload.Sequence, first, len(payload.Data), n, len(buffer)) first = false @@ -663,7 +782,7 @@ func (self *Xgress) sendUnchunkedBuffer(buf []byte, headers map[uint8][]byte) bo payload := &Payload{ CircuitId: self.circuitId, Flags: SetOriginatorFlag(0, self.originator), - Sequence: self.nextReceiveSequence(), + Sequence: int32(self.nextReceiveSequence()), Data: buf, Headers: headers, } @@ -698,7 +817,7 @@ func (self *Xgress) forwardPayload(payload *Payload) bool { return true } -func (self *Xgress) nextReceiveSequence() int32 { +func (self *Xgress) nextReceiveSequence() uint64 { self.rxSequenceLock.Lock() defer self.rxSequenceLock.Unlock() @@ -737,10 +856,10 @@ func (self *Xgress) SendEmptyAck() { acker.ack(ack, self.address) } -func (self *Xgress) GetSequence() int32 { +func (self *Xgress) GetSequence() uint64 { self.rxSequenceLock.Lock() defer self.rxSequenceLock.Unlock() - return self.rxSequence + return uint64(self.rxSequence) } func (self *Xgress) InspectCircuit(detail *inspect.CircuitInspectDetail) { @@ -813,3 +932,129 @@ func (self *Xgress) addGoroutineIfRelated(buf *bytes.Buffer, xgressRelated bool, } return result } + +func UnmarshallPacketPayload(buf []byte) (*channel.Message, error) { + flagsField := buf[0] + if flagsField&1 != 0 { + return channel.ReadV2(bytes.NewBuffer(buf)) + } + version := (flagsField & VersionMask) >> 1 + if version != PayloadProtocolV1 { + return nil, fmt.Errorf("unsupported version: %d", version) + } + sizeField := buf[1] + circuitIdSize := CircuitIdSizeMask & sizeField + rest := buf[2:] + + var rtt *uint16 + if flagsField&RttFlagMask != 0 { + b0 := rest[0] + b1 := rest[1] + rest = rest[2:] + val := uint16(b0) | (uint16(b1) << 8) + rtt = &val + } + + var heartbeat *uint64 + if flagsField&HeartbeatFlagMask != 0 { + val := binary.BigEndian.Uint64(rest[len(rest)-8:]) + heartbeat = &val + rest = rest[:len(rest)-8] + } + + circuitId := string(rest[:circuitIdSize]) + rest = rest[circuitIdSize:] + seq, read := binary.Uvarint(rest) + rest = rest[read:] + + var headers map[uint8][]byte + if flagsField&HeadersFlagMask != 0 { + var err error + headers, rest, err = readU8ToBytesMap(rest) + if err != nil { + return nil, err + } + } + + msg := channel.NewMessage(ContentTypePayloadType, rest) + addPayloadHeadersToMsg(msg, headers) + msg.PutStringHeader(HeaderKeyCircuitId, circuitId) + msg.PutUint64Header(HeaderKeySequence, seq) + if heartbeat != nil { + msg.PutUint64Header(channel.HeartbeatHeader, *heartbeat) + } + msg.Headers[HeaderPayloadRaw] = buf + + flags := uint32(0) + + if flagsField&ChunkFlagMask != 0 { + flags = setPayloadFlag(flags, PayloadFlagChunk) + } + + if flagsField&TerminatorFlagMask != 0 { + flags = setPayloadFlag(flags, PayloadFlagOriginator) + } + + if flags != 0 { + msg.PutUint32Header(HeaderKeyFlags, flags) + } + + if rtt != nil { + msg.PutUint16Header(HeaderKeyRTT, *rtt) + } + + return msg, nil +} + +func writeU8ToBytesMap(m map[uint8][]byte, buf []byte) (int, error) { + written := binary.PutUvarint(buf, uint64(len(m))) + buf = buf[written:] + for k, v := range m { + if len(buf) < 10 { + return 0, fmt.Errorf("header too large, no space for header keys, payload has only %d bytes left", len(buf)) + } + buf[0] = k + written++ + buf = buf[1:] + + fieldLen := binary.PutUvarint(buf, uint64(len(v))) + buf = buf[fieldLen:] + written += fieldLen + if len(buf) < len(v) { + return 0, fmt.Errorf("header too large, no space for header value of size %d, only %d bytes available", len(v), len(buf)) + } + + fieldLen = copy(buf, v) + buf = buf[fieldLen:] + written += fieldLen + } + + return written, nil +} + +func readU8ToBytesMap(buf []byte) (map[uint8][]byte, []byte, error) { + result := map[uint8][]byte{} + count, offset := binary.Uvarint(buf) + if offset < 1 { + return nil, nil, errors.New("error reading payload header map length") + } + buf = buf[offset:] + for i := range count { + if len(buf) < 2 { + return nil, nil, fmt.Errorf("payload header error, ran out of space reading header %d", i) + } + k := buf[0] + valSize, read := binary.Uvarint(buf[1:]) + if read < 1 { + return nil, nil, fmt.Errorf("payload header error, ran out of space reading header %d", i) + } + buf = buf[read+1:] + if len(buf) < int(valSize) { + return nil, nil, fmt.Errorf("payload header error, ran out of space reading header %d", i) + } + result[k] = buf[:valSize] + buf = buf[valSize:] + } + + return result, buf, nil +} diff --git a/router/xgress_common/connection.go b/router/xgress_common/connection.go index e560531e5..8b2df25a6 100644 --- a/router/xgress_common/connection.go +++ b/router/xgress_common/connection.go @@ -18,14 +18,14 @@ package xgress_common import ( "github.com/michaelquigley/pfxlog" - "github.com/openziti/secretstream" - "github.com/openziti/secretstream/kx" "github.com/openziti/channel/v3" - "github.com/openziti/ziti/router/xgress" "github.com/openziti/foundation/v2/concurrenz" "github.com/openziti/foundation/v2/info" "github.com/openziti/sdk-golang/ziti/edge" "github.com/openziti/sdk-golang/ziti/edge/network" + "github.com/openziti/secretstream" + "github.com/openziti/secretstream/kx" + "github.com/openziti/ziti/router/xgress" "github.com/pkg/errors" log "github.com/sirupsen/logrus" "io" diff --git a/router/xlink_transport/dialer.go b/router/xlink_transport/dialer.go index 583819f50..009edd4f4 100644 --- a/router/xlink_transport/dialer.go +++ b/router/xlink_transport/dialer.go @@ -23,6 +23,7 @@ import ( "github.com/openziti/identity" "github.com/openziti/metrics" "github.com/openziti/transport/v2" + "github.com/openziti/ziti/router/xgress" "github.com/openziti/ziti/router/xlink" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -114,6 +115,7 @@ func (self *dialer) dialSplit(linkId *identity.TokenId, address transport.Addres LocalBinding: self.config.localBinding, Headers: headers, TransportConfig: self.transportConfig, + MessageStrategy: channel.DatagramMessageStrategy(xgress.UnmarshallPacketPayload), } payloadDialer := channel.NewClassicDialer(channelDialerConfig) @@ -175,6 +177,7 @@ func (self *dialer) dialSingle(linkId *identity.TokenId, address transport.Addre LocalBinding: self.config.localBinding, Headers: headers, TransportConfig: self.transportConfig, + MessageStrategy: channel.DatagramMessageStrategy(xgress.UnmarshallPacketPayload), }) bindHandler := &dialBindHandler{ diff --git a/router/xlink_transport/listener.go b/router/xlink_transport/listener.go index bfeac6181..c4f414053 100644 --- a/router/xlink_transport/listener.go +++ b/router/xlink_transport/listener.go @@ -24,6 +24,7 @@ import ( "github.com/openziti/metrics" "github.com/openziti/transport/v2" fabricMetrics "github.com/openziti/ziti/common/metrics" + "github.com/openziti/ziti/router/xgress" "github.com/openziti/ziti/router/xlink" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -51,6 +52,7 @@ func (self *listener) Listen() error { TransportConfig: self.tcfg, PoolConfigurator: fabricMetrics.GoroutinesPoolMetricsConfigF(self.metricsRegistry, "pool.listener.link"), ConnectionHandlers: []channel.ConnectionHandler{&ConnectionHandler{self.id}}, + MessageStrategy: channel.DatagramMessageStrategy(xgress.UnmarshallPacketPayload), } var err error diff --git a/zititest/models/dtls-west/actions/bootstrap.go b/zititest/models/dtls-west/actions/bootstrap.go new file mode 100644 index 000000000..3ba8f5f29 --- /dev/null +++ b/zititest/models/dtls-west/actions/bootstrap.go @@ -0,0 +1,130 @@ +/* + (c) Copyright NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package actions + +import ( + "fmt" + "github.com/openziti/ziti/zititest/zitilab" + "time" + + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/model" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "github.com/openziti/ziti/zititest/zitilab/models" +) + +type bootstrapAction struct{} + +func NewBootstrapAction() model.ActionBinder { + action := &bootstrapAction{} + return action.bind +} + +func (a *bootstrapAction) bind(m *model.Model) model.Action { + workflow := actions.Workflow() + + workflow.AddAction(component.Stop(".ctrl")) + workflow.AddAction(host.GroupExec("*", 25, "rm -f logs/*")) + workflow.AddAction(host.GroupExec("component.ctrl", 5, "rm -rf ./fablab/ctrldata")) + + workflow.AddAction(component.Exec("#ctrl", zitilab.ControllerActionInitStandalone)) + workflow.AddAction(component.Start(".ctrl")) + workflow.AddAction(edge.ControllerAvailable("#ctrl", 30*time.Second)) + workflow.AddAction(edge.Login("#ctrl")) + + workflow.AddAction(component.StopInParallel(models.EdgeRouterTag, 25)) + workflow.AddAction(edge.InitEdgeRouters(models.EdgeRouterTag, 2)) + + workflow.AddAction(zitilib_actions.Edge("create", "service", "echo")) + + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "echo-servers", "Bind", "--service-roles", "@echo", "--identity-roles", "#service")) + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "echo-client", "Dial", "--service-roles", "@echo", "--identity-roles", "#client")) + + workflow.AddAction(zitilib_actions.Edge("create", "edge-router-policy", "echo-servers", "--edge-router-roles", "#host", "--identity-roles", "#service")) + workflow.AddAction(zitilib_actions.Edge("create", "edge-router-policy", "echo-clients", "--edge-router-roles", "#client", "--identity-roles", "#client")) + + workflow.AddAction(zitilib_actions.Edge("create", "service-edge-router-policy", "serp-all", "--service-roles", "#all", "--edge-router-roles", "#all")) + + workflow.AddAction(zitilib_actions.Edge("create", "config", "files-host", "host.v1", ` + { + "address" : "localhost", + "port" : 8090, + "protocol" : "tcp" + }`)) + + workflow.AddAction(zitilib_actions.Edge("create", "config", "ssh-host", "host.v1", ` + { + "address" : "localhost", + "port" : 22, + "protocol" : "tcp" + }`)) + + for _, encrypted := range []bool{false, true} { + for _, hostType := range []string{"ert"} { + suffix := "" + encryptionFlag := "ON" + + if !encrypted { + suffix = "-unencrypted" + encryptionFlag = "OFF" + } + + filesConfigName := fmt.Sprintf("files-intercept-%s%s", hostType, suffix) + filesConfigDef := fmt.Sprintf(` + { + "addresses": ["files-%s%s.ziti"], + "portRanges" : [ { "low": 80, "high": 80 } ], + "protocols": ["tcp"] + }`, hostType, suffix) + + workflow.AddAction(zitilib_actions.Edge("create", "config", filesConfigName, "intercept.v1", filesConfigDef)) + + sshConfigName := fmt.Sprintf("ssh-intercept-%s%s", hostType, suffix) + sshConfigDef := fmt.Sprintf(` + { + "addresses": ["ssh-%s%s.ziti"], + "portRanges" : [ { "low": 2022, "high": 2022 } ], + "protocols": ["tcp"] + }`, hostType, suffix) + + workflow.AddAction(zitilib_actions.Edge("create", "config", sshConfigName, "intercept.v1", sshConfigDef)) + + filesServiceName := fmt.Sprintf("%s-files%s", hostType, suffix) + filesConfigs := fmt.Sprintf("files-host,%s", filesConfigName) + workflow.AddAction(zitilib_actions.Edge("create", "service", filesServiceName, "-c", filesConfigs, "-e", encryptionFlag, "-a", hostType)) + + sshServiceName := fmt.Sprintf("%s-ssh%s", hostType, suffix) + sshConfigs := fmt.Sprintf("ssh-host,%s", sshConfigName) + workflow.AddAction(zitilib_actions.Edge("create", "service", sshServiceName, "-c", sshConfigs, "-e", encryptionFlag, "-a", hostType)) + } + } + + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "ert-hosts", "Bind", "--service-roles", "#ert", "--identity-roles", "#ert-host")) + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "zet-hosts", "Bind", "--service-roles", "#zet", "--identity-roles", "#zet-host")) + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "ziti-tunnel-hosts", "Bind", "--service-roles", "#ziti-tunnel", "--identity-roles", "#ziti-tunnel-host")) + workflow.AddAction(zitilib_actions.Edge("create", "service-policy", "client-tunnelers", "Dial", "--service-roles", "#all", "--identity-roles", "#client")) + + workflow.AddAction(zitilib_actions.Edge("create", "edge-router-policy", "client-routers", "--edge-router-roles", "#client", "--identity-roles", "#client")) + workflow.AddAction(zitilib_actions.Edge("create", "edge-router-policy", "host-routers", "--edge-router-roles", "#host", "--identity-roles", "#host")) + + workflow.AddAction(component.Stop(models.ControllerTag)) + + return workflow +} diff --git a/zititest/models/dtls-west/actions/start.go b/zititest/models/dtls-west/actions/start.go new file mode 100644 index 000000000..ead6e6788 --- /dev/null +++ b/zititest/models/dtls-west/actions/start.go @@ -0,0 +1,50 @@ +/* + (c) Copyright NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package actions + +import ( + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "time" + + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/semaphore" + "github.com/openziti/fablab/kernel/model" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/models" +) + +func NewStartAction() model.ActionBinder { + action := &startAction{} + return action.bind +} + +func (a *startAction) bind(m *model.Model) model.Action { + workflow := actions.Workflow() + workflow.AddAction(component.Start(".ctrl")) + workflow.AddAction(edge.ControllerAvailable("#ctrl", 30*time.Second)) + workflow.AddAction(component.StartInParallel(models.EdgeRouterTag, 25)) + + workflow.AddAction(semaphore.Sleep(5 * time.Second)) + workflow.AddAction(edge.Login("#ctrl")) + workflow.AddAction(zitilib_actions.Edge("list", "edge-routers", "limit none")) + workflow.AddAction(zitilib_actions.Edge("list", "terminators", "limit none")) + + return workflow +} + +type startAction struct{} diff --git a/zititest/models/dtls-west/configs/ctrl.yml.tmpl b/zititest/models/dtls-west/configs/ctrl.yml.tmpl new file mode 100644 index 000000000..e05a18c64 --- /dev/null +++ b/zititest/models/dtls-west/configs/ctrl.yml.tmpl @@ -0,0 +1,196 @@ +v: 3 + +{{if .Component.GetFlag "ha"}} +raft: + minClusterSize: 3 + dataDir: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/ctrldata +{{else}} +db: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/ctrl.db +{{end}} + +identity: + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}-server.chain.pem + key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/keys/{{ .Component.Id }}-server.key + ca: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}.chain.pem + +trustDomain: smoke-test + +# the endpoint that routers will connect to the controller over. +ctrl: + listener: tls:0.0.0.0:6262 + options: + advertiseAddress: tls:{{ .Host.PublicIp }}:6262 + # (optional) settings + # set the maximum number of connect requests that are buffered and waiting to be acknowledged (1 to 5000, default 1000) + #maxQueuedConnects: 50 + + # the maximum number of connects that have begun hello synchronization (1 to 1000, default 16) + #maxOutstandingConnects: 100 + + # the number of milliseconds to wait before a hello synchronization fails and closes the connection (30ms to 60000ms, default: 1000ms) + #connectTimeoutMs: 3000 + + # Sets the control channel write timeout. A write timeout will close the control channel, so the router will reconnect + #writeTimeout: 15s + + # A listener address which will be sent to connecting routers in order to change their configured controller + # address. If defined, routers will update address configuration to immediately use the new address for future + # connections. The value of newListener must be resolvable both via DNS and validate via certificates + #newListener: tls:localhost:6262 + +#events: +# jsonLogger: +# subscriptions: +# - type: fabric.routers +# - type: fabric.terminators +# - type: metrics +# sourceFilter: .* +# metricFilter: .*egress.*m1_rate* +# - type: fabric.circuits +# include: +# - created +# - type: edge.sessions +# include: +# - created +# - type: edge.apiSessions +# - type: fabric.usage +# - type: services +# - type: fabric.usage +# - type: edge.entityCounts +# interval: 5s +# handler: +# type: file +# format: json +# path: /tmp/ziti-events.log + +healthChecks: + boltCheck: + # How often to try entering a bolt read tx. Defaults to 30 seconds + interval: 30s + # When to timeout the check. Defaults to 15 seconds + timeout: 15s + # How long to wait before starting the check. Defaults to 15 seconds + initialDelay: 15s + +# By having an 'edge' section defined, the ziti-controller will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the edge to not run. +edge: + # This section represents the configuration of the Edge API that is served over HTTPS + api: + #(optional, default 90s) Alters how frequently heartbeat and last activity values are persisted + # activityUpdateInterval: 90s + #(optional, default 250) The number of API Sessions updated for last activity per transaction + # activityUpdateBatchSize: 250 + # sessionTimeout - optional, default 10m + # The number of minutes before an Edge API session will timeout. Timeouts are reset by + # API requests and connections that are maintained to Edge Routers + sessionTimeout: 30m + # address - required + # The default address (host:port) to use for enrollment for the Client API. This value must match one of the addresses + # defined in a bind point's address field for the `edge-client` API in the web section. + address: {{ .Host.PublicIp }}:1280 + # enrollment - required + # A section containing settings pertaining to enrollment. + enrollment: + # signingCert - required + # A Ziti Identity configuration section that specifically makes use of the cert and key fields to define + # a signing certificate from the PKI that the Ziti environment is using to sign certificates. The signingCert.cert + # will be added to the /.well-known CA store that is used to bootstrap trust with the Ziti Controller. + signingCert: + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/certs/{{ .Component.Id }}.cert + key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/{{ .Component.Id }}/keys/{{ .Component.Id }}.key + + # edgeIdentity - optional + # A section for identity enrollment specific settings + edgeIdentity: + # duration - optional, default 5m + # The length of time that a Ziti Edge Identity enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + duration: 5m + # edgeRouter - Optional + # A section for edge router enrollment specific settings. + edgeRouter: + # duration - optional, default 5m + # The length of time that a Ziti Edge Router enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + duration: 5m + + +# web - optional +# Defines webListeners that will be hosted by the controller. Each webListener can host many APIs and be bound to many +# bind points. +web: + # name - required + # Provides a name for this listener, used for logging output. Not required to be unique, but is highly suggested. + - name: all-apis-localhost + # bindPoints - required + # One or more bind points are required. A bind point specifies an interface (interface:port string) that defines + # where on the host machine the webListener will listen and the address (host:port) that should be used to + # publicly address the webListener(i.e. mydomain.com, localhost, 127.0.0.1). This public address may be used for + # incoming address resolution as well as used in responses in the API. + bindPoints: + #interface - required + # A host:port string on which network interface to listen on. 0.0.0.0 will listen on all interfaces + - interface: 0.0.0.0:1280 + + # address - required + # The public address that external incoming requests will be able to resolve. Used in request processing and + # response content that requires full host:port/path addresses. + address: {{ .Host.PublicIp }}:1280 + + # newAddress - optional + # A host:port string which will be sent out as an HTTP header "ziti-new-address" if specified. If the header + # is present, clients should update location configuration to immediately use the new address for future + # connections. The value of newAddress must be resolvable both via DNS and validate via certificates + #newAddress: localhost:1280 + # identity - optional + # Allows the webListener to have a specific identity instead of defaulting to the root `identity` section. + # identity: + # cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-client.cert.pem + # server_cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-server.cert.pem + # key: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/private/ctrl.key.pem + # ca: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ca-chain.cert.pem + # options - optional + # Allows the specification of webListener level options - mainly dealing with HTTP/TLS settings. These options are + # used for all http servers started by the current webListener. + options: + # idleTimeout - optional, default 5000ms + # The maximum amount of idle time in milliseconds allowed for pipelined HTTP requests. Setting this too high + # can cause resources on the host to be consumed as clients remain connected and idle. Lowering this value + # will cause clients to reconnect on subsequent HTTPs requests. + idleTimeout: 5000ms #http timeouts, new + + # readTimeout - optional, default 5000ms + # The maximum amount of time in milliseconds http servers will wait to read the first incoming requests. A higher + # value risks consuming resources on the host with clients that are acting bad faith or suffering from high latency + # or packet loss. A lower value can risk losing connections to high latency/packet loss clients. + + readTimeout: 5000ms + # writeTimeout - optional, default 10000ms + # The total maximum time in milliseconds that the http server will wait for a single requests to be received and + # responded too. A higher value can allow long running requests to consume resources on the host. A lower value + # can risk ending requests before the server has a chance to respond. + + writeTimeout: 100000ms + # minTLSVersion - optional, default TSL1.2 + # The minimum version of TSL to support + + minTLSVersion: TLS1.2 + # maxTLSVersion - optional, default TSL1.3 + # The maximum version of TSL to support + + maxTLSVersion: TLS1.3 + # apis - required + # Allows one or more APIs to be bound to this webListener + apis: + # binding - required + # Specifies an API to bind to this webListener. Built-in APIs are + # - health-checks + # - edge-management + # - edge-client + # - fabric-management + - binding: health-checks + - binding: fabric + - binding: edge-management + - binding: edge-client + - binding: edge-oidc \ No newline at end of file diff --git a/zititest/models/dtls-west/configs/router.yml.tmpl b/zititest/models/dtls-west/configs/router.yml.tmpl new file mode 100644 index 000000000..c6e5a0d2e --- /dev/null +++ b/zititest/models/dtls-west/configs/router.yml.tmpl @@ -0,0 +1,110 @@ +{{$ssh_username := .Model.MustVariable "credentials.ssh.username"}} +{{$identity := .Component.Id}} +{{$router_ip := .Host.PublicIp}} + +v: 3 + +enableDebugOps: true + +{{if .Component.GetFlag "ha"}} +ha: + enabled: true +{{end}} + +identity: + cert: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-client.cert + server_cert: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-server.cert + key: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}.key + ca: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-server.chain.pem + +ctrl: + endpoints: {{ range $host := .Model.MustSelectHosts "component.ctrl" 1 }} + - tls:{{ $host.PublicIp }}:6262{{end}} + +healthChecks: + ctrlPingCheck: + # How often to ping the controller over the control channel. Defaults to 30 seconds + interval: 30s + # When to timeout the ping. Defaults to 15 seconds + timeout: 15s + # How long to wait before pinging the controller. Defaults to 15 seconds + initialDelay: 15s + +metrics: + reportInterval: 15s + messageQueueSize: 10 + +transport: + westworld3: + profile_version: 1 + #max_segment_sz: 3000 + #dtls: + # maxBytesPerSecond: 500000 + +link: +{{if .Component.HasTag "link.listener"}} + listeners: + - binding: transport + bind: dtls:0.0.0.0:6000 + advertise: dtls:{{$router_ip}}:6000 +{{end}} + dialers: + - binding: transport + split: false + +dialers: + - binding: tunnel + options: + mtu: 1435 + #txPortalStartSize: 4192000 + txPortalIncreaseThresh: 250 + txPortalIncreaseScale: 0.5 + txPortalRetxThresh: 50 + txPortalRetxScale: 0.9 + retxScale: 1.05 + #txPortalMinSize: 4192000 + txPortalIncreaseThresh: 256 + txPortalDupAckThresh: 5 + +listeners: +{{if .Component.HasTag "tunneler"}} + - binding: tunnel + options: + mode: tproxy + mtu: 1435 + #txPortalStartSize: 4192000 + txPortalIncreaseThresh: 250 + txPortalIncreaseScale: 0.5 + txPortalRetxThresh: 50 + txPortalRetxScale: 0.9 + retxScale: 1.05 + #txPortalMinSize: 4192000 + txPortalIncreaseThresh: 256 + txPortalDupAckThresh: 5 + +{{end}} + - binding: edge + address: tls:0.0.0.0:6262 + options: + # (required) The public hostname and port combination that Ziti SDKs should connect on. Previously this was in the chanIngress section. + advertise: {{ .Host.PublicIp }}:6262 + +# By having an 'edge' section defined, the ziti router will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the router to no longer operate as an Edge +# Router. +edge: + # (required) Information used to generate the initial registration CSR. For documentation on these fields please + # refer to the openssl documentation. These values MUST be supplied and have no defaults. + csr: + country: US + province: NC + locality: Charlotte + organization: NetFoundry + organizationalUnit: Ziti + + # (required) SANs that this Gateways certs should contain. At least one IP or DNS SAN should be defined that matches + # the edge listeners "advertise" value from the "listeners" section. + sans: + ip: + - {{ .Host.PublicIp }} + diff --git a/zititest/models/dtls-west/main.go b/zititest/models/dtls-west/main.go new file mode 100644 index 000000000..b2ea903bf --- /dev/null +++ b/zititest/models/dtls-west/main.go @@ -0,0 +1,225 @@ +/* + (c) Copyright NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "embed" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/fablab" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/binding" + "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/aws_ssh_key" + semaphore0 "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/semaphore" + terraform_0 "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/terraform" + distribution "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution" + "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution/rsync" + fablib_5_operation "github.com/openziti/fablab/kernel/lib/runlevel/5_operation" + aws_ssh_key2 "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/aws_ssh_key" + "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/fablab/resources" + "github.com/openziti/ziti/zititest/models/dtls/actions" + "github.com/openziti/ziti/zititest/models/test_resources" + "github.com/openziti/ziti/zititest/zitilab" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "github.com/openziti/ziti/zititest/zitilab/models" + zitilib_5_operation "github.com/openziti/ziti/zititest/zitilab/runlevel/5_operation" + "os" + "strings" + "time" +) + +//go:embed configs +var configResource embed.FS + +func getUniqueId() string { + if runId := os.Getenv("GITHUB_RUN_ID"); runId != "" { + return "-" + runId + "." + os.Getenv("GITHUB_RUN_ATTEMPT") + } + return "-" + os.Getenv("USER") +} + +var Model = &model.Model{ + Id: "dtls-west", + Scope: model.Scope{ + Defaults: model.Variables{ + "environment": "dtls-west" + getUniqueId(), + "credentials": model.Variables{ + "aws": model.Variables{ + "managed_key": true, + }, + "ssh": model.Variables{ + "username": "ubuntu", + }, + "edge": model.Variables{ + "username": "admin", + "password": "admin", + }, + }, + "metrics": model.Variables{ + "influxdb": model.Variables{ + "url": "http://localhost:8086", + "db": "ziti", + }, + }, + }, + }, + + Factories: []model.Factory{ + model.FactoryFunc(func(m *model.Model) error { + pfxlog.Logger().Infof("environment [%s]", m.MustStringVariable("environment")) + m.AddActivationActions("stop", "bootstrap", "start") + return nil + }), + model.FactoryFunc(func(m *model.Model) error { + return m.ForEachHost("*", 1, func(host *model.Host) error { + host.InstanceType = "t2.micro" + return nil + }) + }), + model.FactoryFunc(func(m *model.Model) error { + return m.ForEachHost("component.edge-router", 1, func(host *model.Host) error { + host.InstanceType = "c5.2xlarge" + return nil + }) + }), + //model.FactoryFunc(func(m *model.Model) error { + // return m.ForEachComponent(".edge-router", 1, func(c *model.Component) error { + // c.Type.(*zitilab.RouterType).Version = "v1.1.11" + // return nil + // }) + //}), + }, + + Resources: model.Resources{ + resources.Configs: resources.SubFolder(configResource, "configs"), + resources.Terraform: test_resources.TerraformResources(), + }, + + Regions: model.Regions{ + "us-west-2a": { + Region: "us-west-2", + Site: "us-west-2a", + Hosts: model.Hosts{ + "ctrl": { + Components: model.Components{ + "ctrl": { + Scope: model.Scope{Tags: model.Tags{"ctrl"}}, + Type: &zitilab.ControllerType{}, + }, + }, + }, + "router-client": { + Scope: model.Scope{Tags: model.Tags{"ert-client"}}, + Components: model.Components{ + "router-client": { + Scope: model.Scope{Tags: model.Tags{"edge-router", "terminator", "tunneler", "client"}}, + Type: &zitilab.RouterType{ + Debug: false, + }, + }, + }, + }, + "router-fabric": { + Components: model.Components{ + "router-fabric": { + Scope: model.Scope{Tags: model.Tags{"edge-router", "link.listener"}}, + Type: &zitilab.RouterType{ + Debug: false, + }, + }, + }, + }, + }, + }, + "us-west-2b": { + Region: "us-west-2", + Site: "us-west-2b", + Hosts: model.Hosts{ + "router-host": { + Components: model.Components{ + "router-host": { + Scope: model.Scope{Tags: model.Tags{"edge-router", "tunneler", "host", "ert-host"}}, + Type: &zitilab.RouterType{ + Debug: false, + }, + }, + }, + }, + }, + }, + }, + + Actions: model.ActionBinders{ + "bootstrap": actions.NewBootstrapAction(), + "start": actions.NewStartAction(), + "stop": model.Bind(component.StopInParallel("*", 15)), + "login": model.Bind(edge.Login("#ctrl")), + }, + + Infrastructure: model.Stages{ + aws_ssh_key.Express(), + &terraform_0.Terraform{ + Retries: 3, + ReadyCheck: &semaphore0.ReadyStage{ + MaxWait: 90 * time.Second, + }, + }, + }, + + Distribution: model.Stages{ + distribution.DistributeSshKey("*"), + rsync.RsyncStaged(), + }, + + Disposal: model.Stages{ + terraform.Dispose(), + aws_ssh_key2.Dispose(), + }, + + Operation: model.Stages{ + edge.SyncModelEdgeState(models.EdgeRouterTag), + fablib_5_operation.InfluxMetricsReporter(), + zitilib_5_operation.ModelMetricsWithIdMapper(nil, func(id string) string { + if id == "ctrl" { + return "#ctrl" + } + id = strings.ReplaceAll(id, ".", ":") + return "component.edgeId:" + id + }), + + zitilib_5_operation.CircuitMetrics(time.Second, nil, func(id string) string { + id = strings.ReplaceAll(id, ".", ":") + return "component.edgeId:" + id + }), + model.StageActionF(func(run model.Run) error { + time.Sleep(time.Hour * 24) + return nil + }), + }, +} + +func InitBootstrapExtensions() { + model.AddBootstrapExtension(binding.AwsCredentialsLoader) + model.AddBootstrapExtension(aws_ssh_key.KeyManager) +} + +func main() { + InitBootstrapExtensions() + fablab.InitModel(Model) + fablab.Run() +} diff --git a/zititest/models/dtls/FlowControl.json b/zititest/models/dtls/FlowControl.json new file mode 100644 index 000000000..a2cd46386 --- /dev/null +++ b/zititest/models/dtls/FlowControl.json @@ -0,0 +1,3934 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.windowSize", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "Window Size (Initiator)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.linkSendBufferSize", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "Link Send Buffer Size (initiator)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.linkRecvBufferSize", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "Link Send Buffer Reported Recv Size (initiator)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.recvBuffer.size", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Terminator" + } + ] + } + ], + "title": "Receive Buffer Size (Terminator)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.successfulAcks", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Successful Acks", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.duplicateAcks", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Duplicate Acks", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.retransmits", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Retransmits", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 23 + }, + "id": 17, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.retxThreshold", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Retx Threshold", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "link.dropped_xg_msgs.non_negative_difference { source: router-east-1 }" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "xgress.dropped_payloads", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_fwd_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_rtx_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_xg_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Dropped Payloads", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "circuitId" + ], + "type": "tag" + }, + { + "params": [ + "originator" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "circuit.sendBuffer.retxScale", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "originator", + "operator": "=", + "value": "Initiator" + } + ] + } + ], + "title": "LSB Retx Scale", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 26, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-east-1" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_fwd_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-east-1" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_rtx_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-east-1" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_xg_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-east-1" + } + ] + } + ], + "title": "Dropped Link Payloads (Sender)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 25, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "xgress.dropped_payloads", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-west" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-west" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_fwd_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-west" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_rtx_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-west" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.dropped_xg_msgs", + "orderByTime": "ASC", + "policy": "default", + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Dropped Link Payloads (Recv)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 50 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "ingress.rx.bytesrate", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Ingress Rx", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 50 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "egress.tx.bytesrate", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Egress Tx", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "xgress.retransmissions", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Retransmissions", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "xgress.ack_duplicates", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Duplicate Acks", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 19, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 68 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "source" + ], + "type": "tag" + } + ], + "measurement": "circuit.sendBuffer.blockedByLocalWindow", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + } + ] + ], + "tags": [] + } + ], + "title": "Blocked (Local)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 19, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 68 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "source" + ], + "type": "tag" + } + ], + "hide": false, + "measurement": "circuit.sendBuffer.blockedByRemoteWindow", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + } + ] + ], + "tags": [] + } + ], + "title": "Blocked (Remote)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 19, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 77 + }, + "id": 20, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "source" + ], + "type": "tag" + } + ], + "measurement": "circuit.sendBuffer.blockedByLocalWindow", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + } + ] + ], + "tags": [] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "source" + ], + "type": "tag" + } + ], + "hide": false, + "measurement": "circuit.sendBuffer.blockedByRemoteWindow", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + } + ] + ], + "tags": [] + } + ], + "title": "Blocked", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 6, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "link.rx.msgrate.mean { source: router-west }", + "link.tx.msgrate.mean { source: router-east-1 }" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 77 + }, + "id": 24, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "link.rx.msgrate", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-west" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.tx.msgrate", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-east-1" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "xgress.retransmissions", + "orderByTime": "ASC", + "policy": "default", + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "m1_rate" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-east-1" + } + ] + } + ], + "title": "Link TX vs RX", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 86 + }, + "id": 19, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "xgress.payload_duplicates", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "!=", + "value": "metrics-router" + } + ] + } + ], + "title": "Duplicate Payloads", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 86 + }, + "id": 23, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "xgress.retransmissions", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-east-1" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "bdxepfvogbev4d" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "source" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "link.tx.msgrate", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "count" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "non_negative_difference" + } + ] + ], + "tags": [ + { + "key": "source", + "operator": "=", + "value": "router-east-1" + } + ] + } + ], + "title": "Payloads Vs Rtx", + "type": "timeseries" + } + ], + "refresh": "5s", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "FlowControl", + "uid": "RVzy7lU7z", + "version": 4, + "weekStart": "" +} diff --git a/zititest/models/dtls/configs/router.yml.tmpl b/zititest/models/dtls/configs/router.yml.tmpl index 37b0f9494..c6e5f64a8 100644 --- a/zititest/models/dtls/configs/router.yml.tmpl +++ b/zititest/models/dtls/configs/router.yml.tmpl @@ -38,12 +38,14 @@ transport: westworld3: profile_version: 1 #max_segment_sz: 3000 + #dtls: + # maxBytesPerSecond: 500000 link: listeners: - binding: transport - bind: dtls:0.0.0.0:6000 - advertise: dtls:{{$router_ip}}:6000 + bind: tls:0.0.0.0:6000 + advertise: tls:{{$router_ip}}:6000 dialers: - binding: transport split: false @@ -51,18 +53,31 @@ link: dialers: - binding: tunnel options: - mtu: 8000 - txPortalStartSize: 4192000 - txPortalIncreaseThresh: 28 + #mtu: 1435 + #txPortalStartSize: 4192000 + txPortalIncreaseThresh: 250 + txPortalIncreaseScale: 0.5 + txPortalRetxThresh: 50 + txPortalRetxScale: 0.9 + retxScale: 1.05 + #txPortalMinSize: 4192000 + txPortalIncreaseThresh: 256 listeners: {{if .Component.HasTag "tunneler"}} - binding: tunnel options: mode: tproxy - mtu: 8000 - txPortalStartSize: 4192000 - txPortalIncreaseThresh: 28 + #mtu: 1435 + #txPortalStartSize: 4192000 + txPortalIncreaseThresh: 250 + txPortalIncreaseScale: 0.5 + txPortalRetxThresh: 50 + txPortalRetxScale: 0.9 + retxScale: 1.05 + #txPortalMinSize: 4192000 + txPortalIncreaseThresh: 256 + {{end}} - binding: edge address: tls:0.0.0.0:6262 diff --git a/zititest/models/dtls/main.go b/zititest/models/dtls/main.go index f69962380..828e7c8c1 100644 --- a/zititest/models/dtls/main.go +++ b/zititest/models/dtls/main.go @@ -43,8 +43,6 @@ import ( "time" ) -const ZitiEdgeTunnelVersion = "v2.0.0-alpha1" - //go:embed configs var configResource embed.FS @@ -93,6 +91,18 @@ var Model = &model.Model{ return nil }) }), + model.FactoryFunc(func(m *model.Model) error { + return m.ForEachHost("component.edge-router", 1, func(host *model.Host) error { + host.InstanceType = "c5.xlarge" + return nil + }) + }), + //model.FactoryFunc(func(m *model.Model) error { + // return m.ForEachComponent(".edge-router", 1, func(c *model.Component) error { + // c.Type.(*zitilab.RouterType).Version = "v1.1.11" + // return nil + // }) + //}), }, Resources: model.Resources{ @@ -113,10 +123,10 @@ var Model = &model.Model{ }, }, }, - "router-east-1": { + "router-client": { Scope: model.Scope{Tags: model.Tags{"ert-client"}}, Components: model.Components{ - "router-east-1": { + "router-client": { Scope: model.Scope{Tags: model.Tags{"edge-router", "terminator", "tunneler", "client"}}, Type: &zitilab.RouterType{ Debug: false, @@ -130,9 +140,9 @@ var Model = &model.Model{ Region: "us-west-2", Site: "us-west-2b", Hosts: model.Hosts{ - "router-west": { + "router-host": { Components: model.Components{ - "router-west": { + "router-host": { Scope: model.Scope{Tags: model.Tags{"edge-router", "tunneler", "host", "ert-host"}}, Type: &zitilab.RouterType{ Debug: false,