From 5fc4558d81fcf857019ad3406c14e7741583a259 Mon Sep 17 00:00:00 2001 From: agadiyar Date: Mon, 9 Sep 2019 12:21:11 -0500 Subject: [PATCH 1/5] Added read/write to/from .pcap files --- examples/nffPktgen/testing/minPktLoss.go | 361 ++++++++++++----------- 1 file changed, 194 insertions(+), 167 deletions(-) diff --git a/examples/nffPktgen/testing/minPktLoss.go b/examples/nffPktgen/testing/minPktLoss.go index 9bce7602..3001a142 100644 --- a/examples/nffPktgen/testing/minPktLoss.go +++ b/examples/nffPktgen/testing/minPktLoss.go @@ -5,206 +5,233 @@ package main import ( - "flag" - "fmt" - "os" - "os/signal" - "sync/atomic" - "time" - - "github.com/intel-go/nff-go/examples/nffPktgen/generator" - "github.com/intel-go/nff-go/flow" - "github.com/intel-go/nff-go/packet" + "flag" + "fmt" + "os" + "os/signal" + "sync/atomic" + "time" + + "github.com/intel-go/nff-go/examples/nffPktgen/generator" + "github.com/intel-go/nff-go/flow" + "github.com/intel-go/nff-go/packet" ) type IpPort struct { - Index uint16 - packetCount uint64 - bytesCount uint64 + Index uint16 + packetCount uint64 + bytesCount uint64 } type HandlerContext struct { - port *IpPort + port *IpPort } func (hc HandlerContext) Copy() interface{} { - return HandlerContext{ - port: hc.port, - } + return HandlerContext{ + port: hc.port, + } } func (hc HandlerContext) Delete() { } func main() { - var ( - speed uint64 - tgtLoss float64 - trafDelay uint - genConfig, cores string - inPort uint - outPort uint + var ( + speed uint64 + tgtLoss float64 + trafDelay uint + genConfig, cores string + inPort uint + outPort uint + useReader bool + useWriter bool + inFile string + outFile string + repCount int ) - flag.Uint64Var(&speed, "speed", 120000000, "speed of fast generator, Pkts/s") - flag.Float64Var(&tgtLoss, "target loss", 0.5, "target packet loss percentage") - flag.UintVar(&trafDelay, "traffic delay", 3, "time delay after speed is updated, sec") - flag.StringVar(&genConfig, "config", "ip4.json", "specifies config for generator") - flag.StringVar(&cores, "cores", "", "specifies cores") - flag.UintVar(&outPort, "outPort", 1, "specifies output port") - flag.UintVar(&inPort, "inPort", 1, "specifices input port") - testTime := flag.Uint("t", 0, "run generator for specified period of time in seconds, use zero to run forever") - statInterval := flag.Uint("s", 0, "statistics update interval in seconds, use zero to disable it") - flag.Parse() - - - portStats := IpPort { - Index: uint16(inPort), - } - - // Init NFF-GO system at 16 available cores - config := flow.Config { - CPUList: cores, - } - flow.CheckFatal(flow.SystemInit(&config)) - - configuration, err := generator.ReadConfig(genConfig) - if err != nil { - panic(fmt.Sprintf("%s config reading failed: %v", genConfig, err)) + flag.Uint64Var(&speed, "speed", 120000000, "speed of fast generator, Pkts/s") + flag.Float64Var(&tgtLoss, "target loss", 0.5, "target packet loss percentage") + flag.UintVar(&trafDelay, "traffic delay", 3, "time delay after speed is updated, sec") + flag.StringVar(&genConfig, "config", "ip4.json", "specifies config for generator") + flag.StringVar(&cores, "cores", "", "specifies cores") + flag.UintVar(&outPort, "outPort", 1, "specifies output port") + flag.UintVar(&inPort, "inPort", 1, "specifices input port") + flag.BoolVar(&useReader, "useReader", false, "Enable reader from .pcap file") + flag.BoolVar(&useWriter, "useWriter", false, "Enable writer to .pcap file") + flag.StringVar(&inFile, "inFile", "fileReadWriteIn.pcap", "Input .pcap file") + flag.StringVar(&outFile, "outFile", "fileReadWriteOut.pcap", "Output .pcap file") + flag.IntVar(&repCount, "repCount", 1, "Number of times for reader to read inFile") + testTime := flag.Uint("t", 0, "run generator for specified period of time in seconds, use zero to run forever") + statInterval := flag.Uint("s", 0, "statistics update interval in seconds, use zero to disable it") + flag.Parse() + + + portStats := IpPort { + Index: uint16(inPort), } - context, err := generator.GetContext(configuration) - flow.CheckFatal(err) - outFlow, genChan, _ := flow.SetFastGenerator(generator.Generate, speed, context) - flow.CheckFatal(flow.SetSender(outFlow, uint16(outPort))) - hc := HandlerContext { - port: &portStats, + // Init NFF-GO system at 16 available cores + config := flow.Config { + CPUList: cores, } - inFlow, err := flow.SetReceiver(uint16(inPort)) - flow.CheckFatal(err) - flow.CheckFatal(flow.SetHandlerDrop(inFlow, receiveHandler, hc)) - flow.CheckFatal(flow.SetStopper(inFlow)) - - go func() { - flow.CheckFatal(flow.SystemStart()) - }() - - // Set up finish channels - interruptChannel := make(chan os.Signal, 1) - signal.Notify(interruptChannel, os.Interrupt) - - var finishChannel, statsChannel <-chan time.Time - if *testTime > 0 { - finishChannel = time.NewTicker(time.Duration(*testTime) * time.Second).C - } - if *statInterval > 0 { - statsChannel = time.NewTicker(time.Duration(*statInterval) * time.Second).C - } - - started := time.Now() - - // optimize speed based on packet loss: - maxSpeed := -1 - var maxSpeedPkt float64 = -1 - var totalPktRX, totalPktTX uint64 = 0, 0 - - go func() { - gen := generator.GetGenerator() - low := 0 - high := 100 - currSpeed := 100 - - // data at line rate: - portStats.packetCount = 0 - gen.Count = 0 - time.Sleep(time.Duration(trafDelay) * time.Second) - pktRX := portStats.packetCount - pktTX := gen.GetGeneratedNumber() - pktLoss := calcPktLoss(pktRX, pktTX) - totalPktRX += pktRX - totalPktTX += pktTX - printStats(&portStats, pktRX, pktTX, pktLoss, started, currSpeed, float64(speed)) - - // binary search: - for low <= high { - mid := (low + high) / 2 - currSpeed = mid - updatedSpeed := 0.01 * float64(uint64(currSpeed) * speed) - - // reset counters: - portStats.packetCount = 0 - gen.Count = 0 - - genChan <- uint64(updatedSpeed) - time.Sleep(time.Duration(trafDelay) * time.Second) - - pktRX = portStats.packetCount - pktTX = gen.GetGeneratedNumber() - pktLoss = calcPktLoss(pktRX, pktTX) - - if pktLoss <= tgtLoss { - low = mid + 1 // tgt met so try higher speed - if currSpeed > maxSpeed { - maxSpeed = currSpeed - maxSpeedPkt = updatedSpeed - } - } else { - high = mid - 1 // tgt failed so try lower speed - } - - totalPktRX += pktRX - totalPktTX += pktTX - // fmt.Printf("\nmid: %d\nupdatedSpeed: %d%%(%f pkt/s)\npktCountTX: %d\npktCountRX: %d\npktLoss: %f\nlow: %d\nhigh: %d\n\n", mid, currSpeed, updatedSpeed, pktTX, pktRX, pktLoss, low, high) // debugging purposes - - printStats(&portStats, pktRX, pktTX, pktLoss, started, currSpeed, updatedSpeed) - } - fmt.Printf("--------------------BINARY SEARCH COMPLETE!!!--------------------\n") - interruptChannel <- os.Interrupt - }() + flow.CheckFatal(flow.SystemInit(&config)) + + configuration, err := generator.ReadConfig(genConfig) + if err != nil { + panic(fmt.Sprintf("%s config reading failed: %v", genConfig, err)) + } + context, err := generator.GetContext(configuration) + flow.CheckFatal(err) + outFlow, genChan, _ := flow.SetFastGenerator(generator.Generate, speed, context) + + if useWriter { + println("Write to file", outFile) + flow.CheckFatal(flow.SetSenderFile(outFlow, outFile)) + } else { + println("Send to port", outPort) + flow.CheckFatal(flow.SetSender(outFlow, uint16(outPort))) + } + + hc := HandlerContext { + port: &portStats, + } + + var inFlow *flow.Flow + if useReader { + print("Enabled Read from file ", inFile, " and ") + inFlow = flow.SetReceiverFile(inFile, int32(repCount)) + } else { + print("Enabled Generate and ") + var err error + inFlow, err = flow.SetReceiver(uint16(inPort)) + flow.CheckFatal(err) + } + flow.CheckFatal(flow.SetHandlerDrop(inFlow, receiveHandler, hc)) + flow.CheckFatal(flow.SetStopper(inFlow)) + + go func() { + flow.CheckFatal(flow.SystemStart()) + }() + + // Set up finish channels + interruptChannel := make(chan os.Signal, 1) + signal.Notify(interruptChannel, os.Interrupt) + + var finishChannel, statsChannel <-chan time.Time + if *testTime > 0 { + finishChannel = time.NewTicker(time.Duration(*testTime) * time.Second).C + } + if *statInterval > 0 { + statsChannel = time.NewTicker(time.Duration(*statInterval) * time.Second).C + } + + started := time.Now() + + // optimize speed based on packet loss: + maxSpeed := -1 + var maxSpeedPkt float64 = -1 + var totalPktRX, totalPktTX uint64 = 0, 0 + + go func() { + gen := generator.GetGenerator() + low := 0 + high := 100 + currSpeed := 100 + + // data at line rate: + portStats.packetCount = 0 + gen.Count = 0 + time.Sleep(time.Duration(trafDelay) * time.Second) + pktRX := portStats.packetCount + pktTX := gen.GetGeneratedNumber() + pktLoss := calcPktLoss(pktRX, pktTX) + totalPktRX += pktRX + totalPktTX += pktTX + printStats(&portStats, pktRX, pktTX, pktLoss, started, currSpeed, float64(speed)) + + // binary search: + for low <= high { + mid := (low + high) / 2 + currSpeed = mid + updatedSpeed := 0.01 * float64(uint64(currSpeed) * speed) + + // reset counters: + portStats.packetCount = 0 + gen.Count = 0 + + genChan <- uint64(updatedSpeed) + time.Sleep(time.Duration(trafDelay) * time.Second) + + pktRX = portStats.packetCount + pktTX = gen.GetGeneratedNumber() + pktLoss = calcPktLoss(pktRX, pktTX) + + if pktLoss <= tgtLoss { + low = mid + 1 // tgt met so try higher speed + if currSpeed > maxSpeed { + maxSpeed = currSpeed + maxSpeedPkt = updatedSpeed + } + } else { + high = mid - 1 // tgt failed so try lower speed + } + + totalPktRX += pktRX + totalPktTX += pktTX + // fmt.Printf("\nmid: %d\nupdatedSpeed: %d%%(%f pkt/s)\npktCountTX: %d\npktCountRX: %d\npktLoss: %f\nlow: %d\nhigh: %d\n\n", mid, currSpeed, updatedSpeed, pktTX, pktRX, pktLoss, low, high) // debugging purposes + + printStats(&portStats, pktRX, pktTX, pktLoss, started, currSpeed, updatedSpeed) + } + fmt.Printf("--------------------BINARY SEARCH COMPLETE!!!--------------------\n") + interruptChannel <- os.Interrupt + }() out: - for { - select { - case sig := <-interruptChannel: - fmt.Printf("Received signal %v, finishing.\n", sig) - break out - case <-finishChannel: - fmt.Println("Test timeout reached") - break out - case <-statsChannel: - printStats(&portStats, totalPktRX, totalPktTX, calcPktLoss(totalPktRX, totalPktTX), started, maxSpeed, maxSpeedPkt) - } - } - printTotals(&portStats, totalPktRX, totalPktTX, started, maxSpeed, maxSpeedPkt) + for { + select { + case sig := <-interruptChannel: + fmt.Printf("Received signal %v, finishing.\n", sig) + break out + case <-finishChannel: + fmt.Println("Test timeout reached") + break out + case <-statsChannel: + printStats(&portStats, totalPktRX, totalPktTX, calcPktLoss(totalPktRX, totalPktTX), started, maxSpeed, maxSpeedPkt) + } + } + printTotals(&portStats, totalPktRX, totalPktTX, started, maxSpeed, maxSpeedPkt) } func calcPktLoss(pktCountRX uint64, pktCountTX uint64) float64 { - return (float64(pktCountTX - pktCountRX) / float64(pktCountTX)) * 100.0 + return (float64(pktCountTX - pktCountRX) / float64(pktCountTX)) * 100.0 } func receiveHandler(pkt *packet.Packet, ctx flow.UserContext) bool { - hc := ctx.(HandlerContext) + hc := ctx.(HandlerContext) - atomic.AddUint64(&hc.port.packetCount, 1) - atomic.AddUint64(&hc.port.bytesCount, uint64(pkt.GetPacketLen())) - return true + atomic.AddUint64(&hc.port.packetCount, 1) + atomic.AddUint64(&hc.port.bytesCount, uint64(pkt.GetPacketLen())) + return true } func printStats(port *IpPort, pktRX uint64, pktTX uint64, pktLoss float64, started time.Time, currSpeed int, updatedSpeed float64) { - fmt.Printf("\n%v: ", time.Since(started)) - fmt.Printf("Port %d pkts TX: %d / pkts RX: %d\n", port.Index, pktTX, pktRX) - fmt.Printf("Pkt loss: %f%%\n", pktLoss) - fmt.Printf("Current Speed: %d%% (%f pkts/s)\n\n", currSpeed, updatedSpeed) + fmt.Printf("\n%v: ", time.Since(started)) + fmt.Printf("Port %d pkts TX: %d / pkts RX: %d\n", port.Index, pktTX, pktRX) + fmt.Printf("Pkt loss: %f%%\n", pktLoss) + fmt.Printf("Current Speed: %d%% (%f pkts/s)\n\n", currSpeed, updatedSpeed) } func printTotals(port *IpPort, totalPktRX uint64, totalPktTX uint64, started time.Time, maxSpeed int, maxSpeedPkt float64) { - runtime := time.Since(started) - runtimeint := uint64(runtime) / uint64(time.Second) - totalPktLoss := calcPktLoss(totalPktRX, totalPktTX) - fmt.Printf("\nTest executed for %v\n", runtime) - fmt.Printf("Port %d total pkts TX: %d / pkts RX: %d\n", port.Index, totalPktTX, totalPktRX) - fmt.Printf("Total pkt loss: %f%%\n", totalPktLoss) - fmt.Printf("Port %d pkts/s: %v\n", port.Index, totalPktRX/runtimeint) - fmt.Printf("Port %d kB/s: %v\n", port.Index, port.bytesCount/runtimeint/1000) - fmt.Printf("Max Speed: %d%% (%f pkts/s)\n\n", maxSpeed, maxSpeedPkt) + runtime := time.Since(started) + runtimeint := uint64(runtime) / uint64(time.Second) + totalPktLoss := calcPktLoss(totalPktRX, totalPktTX) + fmt.Printf("\nTest executed for %v\n", runtime) + fmt.Printf("Port %d total pkts TX: %d / pkts RX: %d\n", port.Index, totalPktTX, totalPktRX) + fmt.Printf("Total pkt loss: %f%%\n", totalPktLoss) + fmt.Printf("Port %d pkts/s: %v\n", port.Index, totalPktRX/runtimeint) + fmt.Printf("Port %d kB/s: %v\n", port.Index, port.bytesCount/runtimeint/1000) + fmt.Printf("Max Speed: %d%% (%f pkts/s)\n\n", maxSpeed, maxSpeedPkt) } + From 66e19fb95992babba5b7753689ffce171ae6ccda Mon Sep 17 00:00:00 2001 From: agadiyar Date: Tue, 24 Sep 2019 11:43:42 -0500 Subject: [PATCH 2/5] fixed read from pcap and added trace dump --- examples/nffPktgen/testing/Makefile | 2 +- examples/nffPktgen/testing/minPktLoss.go | 36 ++++++------------------ examples/nffPktgen/testing/pcapGen.json | 5 ++++ 3 files changed, 14 insertions(+), 29 deletions(-) create mode 100644 examples/nffPktgen/testing/pcapGen.json diff --git a/examples/nffPktgen/testing/Makefile b/examples/nffPktgen/testing/Makefile index 8e31b4fe..d2d54c83 100644 --- a/examples/nffPktgen/testing/Makefile +++ b/examples/nffPktgen/testing/Makefile @@ -4,6 +4,6 @@ PATH_TO_MK = ../../../mk IMAGENAME = nff-pktgen -EXECUTABLES = sendGetBack perfTest dump +EXECUTABLES = sendGetBack perfTest dump minPktLoss include $(PATH_TO_MK)/leaf.mk diff --git a/examples/nffPktgen/testing/minPktLoss.go b/examples/nffPktgen/testing/minPktLoss.go index 3001a142..90ae561c 100644 --- a/examples/nffPktgen/testing/minPktLoss.go +++ b/examples/nffPktgen/testing/minPktLoss.go @@ -44,24 +44,16 @@ func main() { genConfig, cores string inPort uint outPort uint - useReader bool - useWriter bool - inFile string - outFile string - repCount int + traceFile string ) flag.Uint64Var(&speed, "speed", 120000000, "speed of fast generator, Pkts/s") flag.Float64Var(&tgtLoss, "target loss", 0.5, "target packet loss percentage") flag.UintVar(&trafDelay, "traffic delay", 3, "time delay after speed is updated, sec") - flag.StringVar(&genConfig, "config", "ip4.json", "specifies config for generator") + flag.StringVar(&genConfig, "config", "pcapGen.json", "specifies config for generator") flag.StringVar(&cores, "cores", "", "specifies cores") flag.UintVar(&outPort, "outPort", 1, "specifies output port") flag.UintVar(&inPort, "inPort", 1, "specifices input port") - flag.BoolVar(&useReader, "useReader", false, "Enable reader from .pcap file") - flag.BoolVar(&useWriter, "useWriter", false, "Enable writer to .pcap file") - flag.StringVar(&inFile, "inFile", "fileReadWriteIn.pcap", "Input .pcap file") - flag.StringVar(&outFile, "outFile", "fileReadWriteOut.pcap", "Output .pcap file") - flag.IntVar(&repCount, "repCount", 1, "Number of times for reader to read inFile") + flag.StringVar(&traceFile, "traceFile", "dumpInput.pcap", "rx pkt trace .pcap file") testTime := flag.Uint("t", 0, "run generator for specified period of time in seconds, use zero to run forever") statInterval := flag.Uint("s", 0, "statistics update interval in seconds, use zero to disable it") flag.Parse() @@ -85,28 +77,16 @@ func main() { flow.CheckFatal(err) outFlow, genChan, _ := flow.SetFastGenerator(generator.Generate, speed, context) - if useWriter { - println("Write to file", outFile) - flow.CheckFatal(flow.SetSenderFile(outFlow, outFile)) - } else { - println("Send to port", outPort) - flow.CheckFatal(flow.SetSender(outFlow, uint16(outPort))) - } + flow.CheckFatal(flow.SetSender(outFlow, uint16(outPort))) hc := HandlerContext { port: &portStats, } - var inFlow *flow.Flow - if useReader { - print("Enabled Read from file ", inFile, " and ") - inFlow = flow.SetReceiverFile(inFile, int32(repCount)) - } else { - print("Enabled Generate and ") - var err error - inFlow, err = flow.SetReceiver(uint16(inPort)) - flow.CheckFatal(err) - } + inFlow, err := flow.SetReceiver(uint16(inPort)) + flow.CheckFatal(err) + dumpFlow, _ := flow.SetCopier(inputFlow) + flow.CheckFatal(flow.SetSenderFile(dumpFlow, traceFile) flow.CheckFatal(flow.SetHandlerDrop(inFlow, receiveHandler, hc)) flow.CheckFatal(flow.SetStopper(inFlow)) diff --git a/examples/nffPktgen/testing/pcapGen.json b/examples/nffPktgen/testing/pcapGen.json new file mode 100644 index 00000000..2d149967 --- /dev/null +++ b/examples/nffPktgen/testing/pcapGen.json @@ -0,0 +1,5 @@ +{ + "ether": { + "pcap-file": "sample-network-sequence.pcap" + } +} From 74698b7bce86a88ce6c058ef16c6963cabe99257 Mon Sep 17 00:00:00 2001 From: agadiyar Date: Tue, 24 Sep 2019 14:18:22 -0500 Subject: [PATCH 3/5] fixed build issue --- examples/nffPktgen/testing/minPktLoss.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nffPktgen/testing/minPktLoss.go b/examples/nffPktgen/testing/minPktLoss.go index 90ae561c..a6c7373a 100644 --- a/examples/nffPktgen/testing/minPktLoss.go +++ b/examples/nffPktgen/testing/minPktLoss.go @@ -86,7 +86,7 @@ func main() { inFlow, err := flow.SetReceiver(uint16(inPort)) flow.CheckFatal(err) dumpFlow, _ := flow.SetCopier(inputFlow) - flow.CheckFatal(flow.SetSenderFile(dumpFlow, traceFile) + flow.CheckFatal(flow.SetSenderFile(dumpFlow, traceFile)) flow.CheckFatal(flow.SetHandlerDrop(inFlow, receiveHandler, hc)) flow.CheckFatal(flow.SetStopper(inFlow)) From b1e6e15dffc2ba1cc0fd4770e6f88ff08ea0b5bf Mon Sep 17 00:00:00 2001 From: agadiyar Date: Tue, 24 Sep 2019 14:39:22 -0500 Subject: [PATCH 4/5] issues with building my nffgo - fixed --- examples/nffPktgen/testing/minPktLoss.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nffPktgen/testing/minPktLoss.go b/examples/nffPktgen/testing/minPktLoss.go index a6c7373a..b9937dca 100644 --- a/examples/nffPktgen/testing/minPktLoss.go +++ b/examples/nffPktgen/testing/minPktLoss.go @@ -85,7 +85,7 @@ func main() { inFlow, err := flow.SetReceiver(uint16(inPort)) flow.CheckFatal(err) - dumpFlow, _ := flow.SetCopier(inputFlow) + dumpFlow, _ := flow.SetCopier(inFlow) flow.CheckFatal(flow.SetSenderFile(dumpFlow, traceFile)) flow.CheckFatal(flow.SetHandlerDrop(inFlow, receiveHandler, hc)) flow.CheckFatal(flow.SetStopper(inFlow)) From a213c8bf7443838d5f92256b3ad5164b8a89fdc2 Mon Sep 17 00:00:00 2001 From: agadiyar Date: Tue, 24 Sep 2019 14:49:46 -0500 Subject: [PATCH 5/5] Updated accessbility of gen pkt count --- examples/nffPktgen/generator/utility.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/nffPktgen/generator/utility.go b/examples/nffPktgen/generator/utility.go index 4f7fae0f..179bf0d0 100644 --- a/examples/nffPktgen/generator/utility.go +++ b/examples/nffPktgen/generator/utility.go @@ -17,7 +17,7 @@ import ( var gen generator type generator struct { - count uint64 + Count uint64 } // GetGenerator returns generator struct pointer @@ -28,7 +28,7 @@ func GetGenerator() *generator { // GetGeneratedNumber returns a number of packets generated func (g *generator) GetGeneratedNumber() uint64 { - return atomic.LoadUint64(&(g.count)) + return atomic.LoadUint64(&(g.Count)) } // ReadConfig function reads and parses config file. @@ -151,6 +151,6 @@ func Generate(pkt *packet.Packet, context flow.UserContext) { } } genP.table[genP.next].generatorFunc(pkt, &genP.table[genP.next].config, genP.rnd) - atomic.AddUint64(&(gen.count), 1) + atomic.AddUint64(&(gen.Count), 1) genP.table[genP.next].have++ }