Skip to content
Snippets Groups Projects
Commit b5e7bb16 authored by S.H.'s avatar S.H.
Browse files

Change benchmark mechanism, adjust readme to account for interactive prompt

parent 223e4f61
No related branches found
No related tags found
No related merge requests found
Pipeline #269891 failed
...@@ -42,8 +42,9 @@ determine the addresses and configuration of the goSDN Controller, Plugin-Regist ...@@ -42,8 +42,9 @@ determine the addresses and configuration of the goSDN Controller, Plugin-Regist
from the SDN-config file in .json. This is combined into a Containerlab configuration that specifies the entire physical network and once this has been deployed with Containerlab, from the SDN-config file in .json. This is combined into a Containerlab configuration that specifies the entire physical network and once this has been deployed with Containerlab,
the .json file is applied to the MongoDB database store with the Northbound Interface (NBI) configuration management service. the .json file is applied to the MongoDB database store with the Northbound Interface (NBI) configuration management service.
After this, a NDT is launched by retrieving the Topology information from the Database and recombining it into a Containerlab yaml file with the base Containerlab file passed in After this, the user is dropped into a simple CLI. A Network Digital Twin (NDT) can be started with `launch-twin`, which retrieves the Topology information from the Database and recombines
earlier. The IP addresses are transposed to avoid conflicts in Docker and the Digital Twin network has its own instances of RabbitMQ, MongoDB, etc. it into a Containerlab yaml file with the base Containerlab file passed in earlier. The IP addresses are transposed to avoid conflicts in Docker and the Digital Twin network has its own
instances of RabbitMQ, MongoDB, etc.
The rtdt-manager subscribes to specific events in the physical network and a callback is triggered when these events occur. In this callback, the YANG path of the data that experienced a change The rtdt-manager subscribes to specific events in the physical network and a callback is triggered when these events occur. In this callback, the YANG path of the data that experienced a change
as well as the new value can be retrieved and are applied to the NDT. as well as the new value can be retrieved and are applied to the NDT.
......
package benchmark
import (
"fmt"
"time"
)
type Benchmark0 struct {
StartTimeRealnet time.Time
SendChangeRequest time.Time
ReceiveChangeRequest time.Time
ReceiveChangeResponse time.Time
ChangeRequestEnd time.Time
SendCommitRequest time.Time
ReceiveCommitResponse time.Time
CommitEnd time.Time
EndTime time.Time
PropagationDelay time.Duration
}
var Current Benchmark0
func (b *Benchmark0) GetDurations() {
startToSend := Diff(b.StartTimeRealnet, b.SendChangeRequest).Microseconds()
fmt.Println("Start to Send:", startToSend)
}
func Diff(start, end time.Time) time.Duration {
duration := end.Sub(start)
return duration
}
func (b *Benchmark0) Print() {
fmt.Println("StartTimeRealnet:")
fmt.Println("SendChangeRequest to ReceiveChangeRequest:", b.ReceiveChangeRequest.Sub(b.SendChangeRequest).Microseconds())
fmt.Println("SendChangeRequest to ChangeRequestEnd:", b.ChangeRequestEnd.Sub(b.SendChangeRequest).Microseconds())
fmt.Println("PropagationDelay:", b.PropagationDelay.Microseconds())
}
...@@ -2,6 +2,8 @@ package rtdtmanager ...@@ -2,6 +2,8 @@ package rtdtmanager
import ( import (
"bufio" "bufio"
"crypto/rand"
"encoding/hex"
"fmt" "fmt"
"os" "os"
"os/signal" "os/signal"
...@@ -20,6 +22,7 @@ import ( ...@@ -20,6 +22,7 @@ import (
"code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/sdnconfig" "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/sdnconfig"
// "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/util" // "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/util"
"code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/benchmark"
"code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/venv" "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/venv"
) )
...@@ -31,6 +34,7 @@ type RtdtManager struct { ...@@ -31,6 +34,7 @@ type RtdtManager struct {
waitGroup sync.WaitGroup waitGroup sync.WaitGroup
stopChan chan os.Signal stopChan chan os.Signal
baseClabConfig *clabconfig.ClabConfig baseClabConfig *clabconfig.ClabConfig
benchmark0 bool
} }
// needs to be passed a running realnet VEnv // needs to be passed a running realnet VEnv
...@@ -40,6 +44,7 @@ func NewRtdtManager() *RtdtManager { ...@@ -40,6 +44,7 @@ func NewRtdtManager() *RtdtManager {
waitGroup: sync.WaitGroup{}, waitGroup: sync.WaitGroup{},
stopChan: make(chan os.Signal, 1), stopChan: make(chan os.Signal, 1),
baseClabConfig: nil, baseClabConfig: nil,
benchmark0: false,
} }
signal.Notify(rMan.stopChan, os.Interrupt) signal.Notify(rMan.stopChan, os.Interrupt)
fmt.Println("Success: RtdtManager created") fmt.Println("Success: RtdtManager created")
...@@ -240,27 +245,36 @@ func (r *RtdtManager) ApplyEvents(twinName string) error { ...@@ -240,27 +245,36 @@ func (r *RtdtManager) ApplyEvents(twinName string) error {
return nil return nil
} }
// Performance benchmarks of realnet // Performance benchmarks of twin, change hostname to random string
func (r *RtdtManager) RunBenchmark0() error { func (r *RtdtManager) RunBenchmark0(numTests int64) error {
var mneid string var mneid string
r.benchmark0 = true
for _, node := range r.realnet.GetSdnConfig().Nodes { for _, node := range r.realnet.GetSdnConfig().Nodes {
if strings.HasPrefix(node.Name, "gnmi-target-switch0") { if strings.HasPrefix(node.Name, "gnmi-target-switch0") {
mneid = node.ID mneid = node.ID
} }
} }
numTests := int64(200) //results := make([]time.Duration, numTests)
results := make([]time.Duration, numTests)
// Change a property and measure the time when it's applied // Change a property and measure the time when it's applied
for i, value := 0, int64(2001); i < int(numTests); i, value = i+1, value+1 { for i, value := 0, int64(2001); i < int(numTests); i, value = i+1, value+1 {
t1 := time.Now() randBytes := make([]byte, 4)
r.realnet.SetGnmiPath("/interfaces/interface[name=eth2]/config/mtu", strconv.FormatInt(value, 10), mneid, false) _, err := rand.Read(randBytes)
timeDiff := time.Now().Sub(t1) if err != nil {
results[i] = timeDiff fmt.Println("couldn't create random hostname")
} return err
}
randname := hex.EncodeToString(randBytes)
//r.realnet.SetGnmiPath("/interfaces/interface[name=eth2]/config/mtu", strconv.FormatInt(value, 10), mneid, false)
err = r.realnet.SetGnmiPath("/system/config/hostname", randname, mneid, false)
if err != nil {
fmt.Printf("Encountered error: %v\n", err)
}
for i, res := range results {
fmt.Printf("%d - %v\n", i, res)
} }
// for i, res := range results {
// fmt.Printf("%d - %v\n", i, res)
// }
return nil return nil
} }
...@@ -347,8 +361,19 @@ func (r *RtdtManager) Run() error { ...@@ -347,8 +361,19 @@ func (r *RtdtManager) Run() error {
} }
case "benchmark": case "benchmark":
fmt.Printf("Launching benchmark!\n") var numTests int64
r.RunBenchmark0() var err error
if len(tokens) == 2 {
numTests, err = strconv.ParseInt(tokens[1], 10, 64)
if err != nil {
r.RunBenchmark0(numTests)
} else {
fmt.Printf("Couldn't parse second argument as int64\n")
break
}
} else {
r.RunBenchmark0(1)
}
case "exit", "quit": case "exit", "quit":
close(r.stopChan) close(r.stopChan)
return return
...@@ -356,7 +381,7 @@ func (r *RtdtManager) Run() error { ...@@ -356,7 +381,7 @@ func (r *RtdtManager) Run() error {
fmt.Println("Available commands:") fmt.Println("Available commands:")
fmt.Println(" launch-twin Launch a twin with default options") fmt.Println(" launch-twin Launch a twin with default options")
fmt.Println(" launch-twin <IPv4> <IPv6> <name> Launch a twin with specified network ranges and name") fmt.Println(" launch-twin <IPv4> <IPv6> <name> Launch a twin with specified network ranges and name")
fmt.Println(" playback Play changes recorded by twin back to realnet") fmt.Println(" playback Play changes recorded by twin back to realnet")
fmt.Println(" benchmark Measure propagation delay of twin") fmt.Println(" benchmark Measure propagation delay of twin")
fmt.Println(" exit / quit Exit the program") fmt.Println(" exit / quit Exit the program")
} }
...@@ -453,13 +478,16 @@ func (r *RtdtManager) updateMNECallbackTwin(event *event.Event) { ...@@ -453,13 +478,16 @@ func (r *RtdtManager) updateMNECallbackTwin(event *event.Event) {
r.rtdt_twins[0].SavedEvents = append(r.rtdt_twins[0].SavedEvents, event) r.rtdt_twins[0].SavedEvents = append(r.rtdt_twins[0].SavedEvents, event)
fmt.Printf("Saved change with path %s and value %s\n", path, value) fmt.Printf("Saved change with path %s and value %s\n", path, value)
} }
} }
func (r *RtdtManager) updateMNECallbackRealnet(event *event.Event) { func (r *RtdtManager) updateMNECallbackRealnet(event *event.Event) {
if !r.realnet.SyncBack { if !r.realnet.SyncBack {
return return
} }
var b0 benchmark.Benchmark0
if r.benchmark0 {
b0.StartTimeRealnet = time.Now()
}
fmt.Println("--------------------------------") fmt.Println("--------------------------------")
fmt.Println("---------- MNE EVENT -----------") fmt.Println("---------- MNE EVENT -----------")
fmt.Println("EventID: ", event.ID.ID()) fmt.Println("EventID: ", event.ID.ID())
...@@ -509,7 +537,7 @@ func (r *RtdtManager) updateMNECallbackRealnet(event *event.Event) { ...@@ -509,7 +537,7 @@ func (r *RtdtManager) updateMNECallbackRealnet(event *event.Event) {
if strings.HasPrefix(path, prefix) && strings.HasSuffix(path, suffixMTU) { if strings.HasPrefix(path, prefix) && strings.HasSuffix(path, suffixMTU) {
fmt.Println("--- CHANGE MTU TRIGGERED ---") fmt.Println("--- CHANGE MTU TRIGGERED ---")
fmt.Println("Value of new MTU: ", value) fmt.Println("Value of new MTU: ", value)
twin.SetGnmiPath(path, value, twinEntityID, false) twin.SetGnmiPath(path, value, twinEntityID, r.benchmark0)
// Set Hostname // Set Hostname
} else if strings.HasPrefix(path, prefixHostname) { } else if strings.HasPrefix(path, prefixHostname) {
// Hostname change // Hostname change
...@@ -520,7 +548,7 @@ func (r *RtdtManager) updateMNECallbackRealnet(event *event.Event) { ...@@ -520,7 +548,7 @@ func (r *RtdtManager) updateMNECallbackRealnet(event *event.Event) {
continue continue
} }
fmt.Println("ENTERING SETGNMIPATH, value: ", value, "path:", path) fmt.Println("ENTERING SETGNMIPATH, value: ", value, "path:", path)
err = twin.SetGnmiPath(path, value, twinEntityID, false) err = twin.SetGnmiPath(path, value, twinEntityID, r.benchmark0)
if err != nil { if err != nil {
fmt.Println("Callback failed:", err) fmt.Println("Callback failed:", err)
return return
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
) )
func Now() int64 { func Now() int64 {
return int64(time.Now().UnixNano()) return time.Now().UnixNano()
} }
func GenerateGosdnPath() (string, error) { func GenerateGosdnPath() (string, error) {
......
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
topoPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/topology" topoPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/topology"
tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport" tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
"code.fbi.h-da.de/danet/gosdn/application-framework/event" "code.fbi.h-da.de/danet/gosdn/application-framework/event"
"code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/benchmark"
clab "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/clab-config" clab "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/clab-config"
clabconfig "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/clab-config" clabconfig "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/clab-config"
"code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/gosdnutil" "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/gosdnutil"
...@@ -273,7 +274,7 @@ func getTypedValue(value, ytype string) (*gnmi.TypedValue, error) { ...@@ -273,7 +274,7 @@ func getTypedValue(value, ytype string) (*gnmi.TypedValue, error) {
return nil, err return nil, err
} }
} }
case "uint16": case "uint16", "uint32", "uint64":
{ {
uintVal, err := strconv.ParseUint(value, 10, 64) uintVal, err := strconv.ParseUint(value, 10, 64)
if err == nil { if err == nil {
...@@ -315,25 +316,18 @@ func (v *VEnv) SetGnmiPath(path, value, mneid string, save bool) error { ...@@ -315,25 +316,18 @@ func (v *VEnv) SetGnmiPath(path, value, mneid string, save bool) error {
return fmt.Errorf("Encountered error while trying to parse string path into gnmi path: %w", err) return fmt.Errorf("Encountered error while trying to parse string path into gnmi path: %w", err)
} }
//ytypes.GetOrCreateNode(gnmitargetygot.Schema(), ,gnmiPath) //ytypes.GetOrCreateNode(gnmitargetygot.Schema(), ,gnmiPath)
fmt.Println("GETTING SCHEMA")
schema, nil := gnmitargetygot.Schema() schema, nil := gnmitargetygot.Schema()
fmt.Println("GETTING ROOT SCHEMA")
rootSchema := schema.RootSchema() rootSchema := schema.RootSchema()
fmt.Println("GET OR CREATE NODE")
_, entry, err := ytypes.GetOrCreateNode(rootSchema, &gnmitargetygot.Gnmitarget{}, gnmiPath) _, entry, err := ytypes.GetOrCreateNode(rootSchema, &gnmitargetygot.Gnmitarget{}, gnmiPath)
if err != nil { if err != nil {
return fmt.Errorf("SetGnnmiPath Error: %w", err) return fmt.Errorf("SetGnnmiPath Error: %w", err)
} }
//gosdnAddr := v.auth.GetAddress()
fmt.Println("GET TYPED VALUE")
yangType := entry.Type yangType := entry.Type
gnmiVal, err := getTypedValue(value, yangType.Kind.String()) gnmiVal, err := getTypedValue(value, yangType.Kind.String())
if err != nil { if err != nil {
fmt.Println("The given type is not supported yet!") fmt.Println("The given type is not supported yet!")
} }
// fmt.Println("YangType Name is ", yangType.Name) fmt.Println("gnmiVal:", gnmiVal)
// fmt.Println("YangType Type is ", yangType.Type)
// fmt.Println("YangType Kind is ", yangType.Kind.String())
changeRequest := &networkelement.ChangeRequest{ changeRequest := &networkelement.ChangeRequest{
Mneid: mneid, Mneid: mneid,
...@@ -345,11 +339,18 @@ func (v *VEnv) SetGnmiPath(path, value, mneid string, save bool) error { ...@@ -345,11 +339,18 @@ func (v *VEnv) SetGnmiPath(path, value, mneid string, save bool) error {
changeRequests := []*networkelement.ChangeRequest{changeRequest} changeRequests := []*networkelement.ChangeRequest{changeRequest}
pid := v.pnd.Id pid := v.pnd.Id
setPathResponse, err := mneService.SetPathList(ctx, &networkelement.SetPathListRequest{ if save {
benchmark.Current.SendChangeRequest = time.Now()
}
setPathListReq := &networkelement.SetPathListRequest{
Timestamp: util.Now(), Timestamp: util.Now(),
Pid: pid, Pid: pid,
ChangeRequest: changeRequests, ChangeRequest: changeRequests,
}) }
setPathResponse, err := mneService.SetPathList(ctx, setPathListReq)
if save {
benchmark.Current.ChangeRequestEnd = time.Now()
}
if err != nil { if err != nil {
fmt.Printf("Error: %v\n", err) fmt.Printf("Error: %v\n", err)
return err return err
...@@ -368,15 +369,31 @@ func (v *VEnv) SetGnmiPath(path, value, mneid string, save bool) error { ...@@ -368,15 +369,31 @@ func (v *VEnv) SetGnmiPath(path, value, mneid string, save bool) error {
Pid: pid, Pid: pid,
} }
clResponse, err := mneService.SetChangeList(ctx, &setChangeListRequest) clResponse, err := mneService.SetChangeList(ctx, &setChangeListRequest)
if save {
benchmark.Current.CommitEnd = time.Now()
}
if err != nil { if err != nil {
fmt.Println("Error, failed to commit changes:", err) fmt.Println("Error, failed to commit changes:", err)
return err return err
} else { } else {
fmt.Println("Successfully applied changes:", clResponse) fmt.Println("Successfully applied changes:", clResponse)
if save {
benchmark.Current.CommitEnd = time.Now()
}
}
if save {
benchmark.Current.SendChangeRequest = time.Unix(0, setPathListReq.Timestamp) // send req in realnet
benchmark.Current.ReceiveChangeRequest = time.Unix(0, setPathResponse.Timestamp) // rcv in twin
benchmark.Current.SendCommitRequest = time.Unix(0, setChangeListRequest.Timestamp)
benchmark.Current.ReceiveCommitResponse = time.Unix(0, clResponse.Timestamp)
benchmark.Current.PropagationDelay = benchmark.Current.StartTimeRealnet.Sub(benchmark.Current.EndTime)
fmt.Println("---Measurement finished---")
benchmark.Current.Print()
} }
// if save {
// v.SavedChanges = append(v.SavedChanges, changeRequest)
// }
return nil return nil
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment