diff --git a/Dockerfile b/Dockerfile
index 96c84f70..b6fe71a4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -21,7 +21,7 @@ RUN apt-get -q update && apt-get -q -y install \
libmnl-dev \
libibverbs-dev
-RUN cd /opt && curl -L -s https://dl.google.com/go/go1.11.4.linux-amd64.tar.gz | tar zx
+RUN cd /opt && curl -L -s https://dl.google.com/go/go1.11.5.linux-amd64.tar.gz | tar zx
RUN mkdir -p ${NFF_GO}
COPY . ${NFF_GO}
diff --git a/common/common.go b/common/common.go
index 959c4293..50631c97 100644
--- a/common/common.go
+++ b/common/common.go
@@ -7,332 +7,9 @@
package common
import (
- "fmt"
- "io"
- "log"
- "math"
- "os"
"strconv"
-
- "github.com/pkg/errors"
-)
-
-// Max array length for type conversions
-const MaxLength = math.MaxInt32
-
-// Length of addresses.
-const (
- EtherAddrLen = 6
- IPv4AddrLen = 4
- IPv6AddrLen = 16
-)
-
-// Supported EtherType for L2
-const (
- IPV4Number = 0x0800
- ARPNumber = 0x0806
- VLANNumber = 0x8100
- MPLSNumber = 0x8847
- IPV6Number = 0x86dd
-
- SwapIPV4Number = 0x0008
- SwapARPNumber = 0x0608
- SwapVLANNumber = 0x0081
- SwapMPLSNumber = 0x4788
- SwapIPV6Number = 0xdd86
-)
-
-// Supported L4 types
-const (
- ICMPNumber = 0x01
- IPNumber = 0x04
- TCPNumber = 0x06
- UDPNumber = 0x11
- ICMPv6Number = 0x3a
- NoNextHeader = 0x3b
-)
-
-// Supported ICMP Types
-const (
- ICMPTypeEchoRequest uint8 = 8
- ICMPTypeEchoResponse uint8 = 0
- ICMPv6TypeEchoRequest uint8 = 128
- ICMPv6TypeEchoResponse uint8 = 129
- ICMPv6NeighborSolicitation uint8 = 135
- ICMPv6NeighborAdvertisement uint8 = 136
-)
-
-// These constants keep length of supported headers in bytes.
-//
-// IPv6Len - minimum length of IPv6 header in bytes. It can be higher and it
-// is not determined inside packet. Only default minimum size is used.
-//
-// IPv4MinLen and TCPMinLen are used only in packet generation functions.
-//
-// In parsing we take actual length of TCP header from DataOff field and length of
-// IPv4 take from Ihl field.
-const (
- EtherLen = 14
- VLANLen = 4
- MPLSLen = 4
- IPv4MinLen = 20
- IPv6Len = 40
- ICMPLen = 8
- TCPMinLen = 20
- UDPLen = 8
- ARPLen = 28
- GTPMinLen = 8
-)
-
-const (
- TCPMinDataOffset = 0x50 // minimal tcp data offset
- IPv4VersionIhl = 0x45 // IPv4, IHL = 5 (min header len)
- IPv6VtcFlow = 0x60 // IPv6 version
-)
-
-// LogType - type of logging, used in flow package
-type LogType uint8
-
-const (
- // No - no output even after fatal errors
- No LogType = 1 << iota
- // Initialization - output during system initialization
- Initialization = 2
- // Debug - output during execution one time per time period (scheduler ticks)
- Debug = 4
- // Verbose - output during execution as soon as something happens. Can influence performance
- Verbose = 8
-)
-
-// TCPFlags contains set TCP flags.
-type TCPFlags uint8
-
-// Constants for valuues of TCP flags.
-const (
- TCPFlagFin = 0x01
- TCPFlagSyn = 0x02
- TCPFlagRst = 0x04
- TCPFlagPsh = 0x08
- TCPFlagAck = 0x10
- TCPFlagUrg = 0x20
- TCPFlagEce = 0x40
- TCPFlagCwr = 0x80
)
-// ErrorCode type for codes of errors
-type ErrorCode int
-
-// constants with error codes
-const (
- _ ErrorCode = iota
- Fail
- ParseCPUListErr
- ReqTooManyPorts
- BadArgument
- UseNilFlowErr
- UseClosedFlowErr
- OpenedFlowAtTheEnd
- PortHasNoQueues
- NotAllQueuesUsed
- FailToInitPort
- ParseRuleJSONErr
- FileErr
- ParseRuleErr
- IncorrectArgInRules
- IncorrectRule
- AllocMbufErr
- PktMbufHeadRoomTooSmall
- NotEnoughCores
- CreatePortErr
- MaxCPUExceedErr
- PcapReadFail
- PcapWriteFail
- InvalidCPURangeErr
- SetAffinityErr
- MultipleReceivePort
- MultipleKNIPort
- WrongPort
- FailToInitDPDK
- FailToCreateKNI
- FailToReleaseKNI
-)
-
-// NFError is error type returned by nff-go functions
-type NFError struct {
- Code ErrorCode
- Message string
- CauseErr error
-}
-
-type causer interface {
- Cause() error
-}
-
-// Error method to implement error interface
-func (err NFError) Error() string {
- return fmt.Sprintf("%s (%d)", err.Message, err.Code)
-}
-
-// GetNFErrorCode returns value of cCode field if err is
-// NFError or pointer to it and -1 otherwise.
-func GetNFErrorCode(err error) ErrorCode {
- if nferr := GetNFError(err); nferr != nil {
- return nferr.Code
- }
- return -1
-}
-
-func checkAndGetNFErrPointer(err error) *NFError {
- if err != nil {
- if nferr, ok := err.(NFError); ok {
- return &nferr
- } else if nferr, ok := err.(*NFError); ok {
- return nferr
- }
- }
- return nil
-}
-
-// GetNFError if error is NFerror or pointer to int
-// returns pointer to NFError, otherwise returns nil.
-func GetNFError(err error) (nferr *NFError) {
- nferr = checkAndGetNFErrPointer(err)
- if nferr == nil {
- if cause, ok := err.(causer); ok {
- nferr = checkAndGetNFErrPointer(cause.Cause())
- }
- }
- return nferr
-}
-
-// Cause returns the underlying cause of error, if
-// possible. If not, returns err itself.
-func (err *NFError) Cause() error {
- if err == nil {
- return nil
- }
- if err.CauseErr != nil {
- if cause, ok := err.CauseErr.(causer); ok {
- return cause.Cause()
- }
- return err.CauseErr
- }
- return err
-}
-
-// Format makes formatted printing of errors,
-// the following verbs are supported:
-// %s, %v print the error. If the error has a
-// Cause it will be printed recursively
-// %+v - extended format. Each Frame of the error's
-// StackTrace will be printed in detail if possible.
-func (err *NFError) Format(s fmt.State, verb rune) {
- switch verb {
- case 'v':
- if s.Flag('+') {
- if cause := err.Cause(); cause != err && cause != nil {
- fmt.Fprintf(s, "%+v\n", err.Cause())
- io.WriteString(s, err.Message)
- return
- }
- }
- fallthrough
- case 's', 'q':
- io.WriteString(s, err.Error())
- }
-}
-
-// WrapWithNFError returns an error annotating err with a stack trace
-// at the point WrapWithNFError is called, and the next our NFError.
-// If err is nil, Wrap returns nil.
-func WrapWithNFError(err error, message string, code ErrorCode) error {
- err = &NFError{
- CauseErr: err,
- Message: message,
- Code: code,
- }
- return errors.WithStack(err)
-}
-
-var currentLogType = No | Initialization | Debug
-
-// LogFatal internal, used in all packages
-func LogFatal(logType LogType, v ...interface{}) {
- if logType¤tLogType != 0 {
- t := fmt.Sprintln(v...)
- log.Fatal("ERROR: ", t)
- }
- os.Exit(1)
-}
-
-// LogFatalf is a wrapper at LogFatal which makes formatting before logger.
-func LogFatalf(logType LogType, format string, v ...interface{}) {
- LogFatal(logType, fmt.Sprintf(format, v...))
-}
-
-// LogError internal, used in all packages
-func LogError(logType LogType, v ...interface{}) string {
- if logType¤tLogType != 0 {
- t := fmt.Sprintln(v...)
- log.Print("ERROR: ", t)
- return t
- }
- return ""
-}
-
-// LogWarning internal, used in all packages
-func LogWarning(logType LogType, v ...interface{}) {
- if logType¤tLogType != 0 {
- t := fmt.Sprintln(v...)
- log.Print("WARNING: ", t)
- }
-}
-
-// LogDebug internal, used in all packages
-func LogDebug(logType LogType, v ...interface{}) {
- if logType¤tLogType != 0 {
- t := fmt.Sprintln(v...)
- log.Print("DEBUG: ", t)
- }
-}
-
-// LogDrop internal, used in all packages
-func LogDrop(logType LogType, v ...interface{}) {
- if logType¤tLogType != 0 {
- t := fmt.Sprintln(v...)
- log.Print("DROP: ", t)
- }
-}
-
-// LogTitle internal, used in all packages
-func LogTitle(logType LogType, v ...interface{}) {
- if logType¤tLogType != 0 {
- log.Print(v...)
- }
-}
-
-// SetLogType internal, used in flow package
-func SetLogType(logType LogType) {
- log.SetFlags(0)
- currentLogType = logType
-}
-
-// GetDPDKLogLevel internal, used in flow package
-func GetDPDKLogLevel() string {
- switch currentLogType {
- case No:
- return "0"
- case No | Initialization:
- return "7"
- case No | Initialization | Debug:
- return "8"
- case No | Initialization | Debug | Verbose:
- return "8"
- default:
- return "8"
- }
-}
-
// GetDefaultCPUs returns default core list {0, 1, ..., NumCPU}
func GetDefaultCPUs(cpuNumber int) []int {
cpus := make([]int, cpuNumber, cpuNumber)
@@ -420,3 +97,9 @@ func dropInvalidCPUs(nums []int, maxcpu int) []int {
}
return nums[:i]
}
+
+// RXTXStats describes statistics for sender or receiver flow function
+// node.
+type RXTXStats struct {
+ PacketsProcessed, PacketsDropped, BytesProcessed uint64
+}
diff --git a/common/error.go b/common/error.go
new file mode 100644
index 00000000..df74f9ec
--- /dev/null
+++ b/common/error.go
@@ -0,0 +1,148 @@
+// Copyright 2019 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package common
+
+import (
+ "fmt"
+ "io"
+
+ "github.com/pkg/errors"
+)
+
+// ErrorCode type for codes of errors
+type ErrorCode int
+
+// constants with error codes
+const (
+ _ ErrorCode = iota
+ Fail
+ ParseCPUListErr
+ ReqTooManyPorts
+ BadArgument
+ UseNilFlowErr
+ UseClosedFlowErr
+ OpenedFlowAtTheEnd
+ PortHasNoQueues
+ NotAllQueuesUsed
+ FailToInitPort
+ ParseRuleJSONErr
+ FileErr
+ ParseRuleErr
+ IncorrectArgInRules
+ IncorrectRule
+ AllocMbufErr
+ PktMbufHeadRoomTooSmall
+ NotEnoughCores
+ CreatePortErr
+ MaxCPUExceedErr
+ PcapReadFail
+ PcapWriteFail
+ InvalidCPURangeErr
+ SetAffinityErr
+ MultipleReceivePort
+ MultipleKNIPort
+ WrongPort
+ FailToInitDPDK
+ FailToCreateKNI
+ FailToReleaseKNI
+ BadSocket
+)
+
+// NFError is error type returned by nff-go functions
+type NFError struct {
+ Code ErrorCode
+ Message string
+ CauseErr error
+}
+
+type causer interface {
+ Cause() error
+}
+
+// Error method to implement error interface
+func (err NFError) Error() string {
+ return fmt.Sprintf("%s (%d)", err.Message, err.Code)
+}
+
+// GetNFErrorCode returns value of cCode field if err is
+// NFError or pointer to it and -1 otherwise.
+func GetNFErrorCode(err error) ErrorCode {
+ if nferr := GetNFError(err); nferr != nil {
+ return nferr.Code
+ }
+ return -1
+}
+
+func checkAndGetNFErrPointer(err error) *NFError {
+ if err != nil {
+ if nferr, ok := err.(NFError); ok {
+ return &nferr
+ } else if nferr, ok := err.(*NFError); ok {
+ return nferr
+ }
+ }
+ return nil
+}
+
+// GetNFError if error is NFerror or pointer to int
+// returns pointer to NFError, otherwise returns nil.
+func GetNFError(err error) (nferr *NFError) {
+ nferr = checkAndGetNFErrPointer(err)
+ if nferr == nil {
+ if cause, ok := err.(causer); ok {
+ nferr = checkAndGetNFErrPointer(cause.Cause())
+ }
+ }
+ return nferr
+}
+
+// Cause returns the underlying cause of error, if
+// possible. If not, returns err itself.
+func (err *NFError) Cause() error {
+ if err == nil {
+ return nil
+ }
+ if err.CauseErr != nil {
+ if cause, ok := err.CauseErr.(causer); ok {
+ return cause.Cause()
+ }
+ return err.CauseErr
+ }
+ return err
+}
+
+// Format makes formatted printing of errors,
+// the following verbs are supported:
+// %s, %v print the error. If the error has a
+// Cause it will be printed recursively
+// %+v - extended format. Each Frame of the error's
+// StackTrace will be printed in detail if possible.
+func (err *NFError) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ if s.Flag('+') {
+ if cause := err.Cause(); cause != err && cause != nil {
+ fmt.Fprintf(s, "%+v\n", err.Cause())
+ io.WriteString(s, err.Message)
+ return
+ }
+ }
+ fallthrough
+ case 's', 'q':
+ io.WriteString(s, err.Error())
+ }
+}
+
+// WrapWithNFError returns an error annotating err with a stack trace
+// at the point WrapWithNFError is called, and the next our NFError.
+// If err is nil, Wrap returns nil.
+func WrapWithNFError(err error, message string, code ErrorCode) error {
+ err = &NFError{
+ CauseErr: err,
+ Message: message,
+ Code: code,
+ }
+ return errors.WithStack(err)
+}
diff --git a/common/log.go b/common/log.go
new file mode 100644
index 00000000..e71fadf6
--- /dev/null
+++ b/common/log.go
@@ -0,0 +1,104 @@
+// Copyright 2019 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package common
+
+import (
+ "fmt"
+ "log"
+ "os"
+)
+
+// LogType - type of logging, used in flow package
+type LogType uint8
+
+const (
+ // No - no output even after fatal errors
+ No LogType = 1 << iota
+ // Initialization - output during system initialization
+ Initialization = 2
+ // Debug - output during execution one time per time period (scheduler ticks)
+ Debug = 4
+ // Verbose - output during execution as soon as something happens. Can influence performance
+ Verbose = 8
+)
+
+var currentLogType = No | Initialization | Debug
+
+// LogFatal internal, used in all packages
+func LogFatal(logType LogType, v ...interface{}) {
+ if logType¤tLogType != 0 {
+ t := fmt.Sprintln(v...)
+ log.Fatal("ERROR: ", t)
+ }
+ os.Exit(1)
+}
+
+// LogFatalf is a wrapper at LogFatal which makes formatting before logger.
+func LogFatalf(logType LogType, format string, v ...interface{}) {
+ LogFatal(logType, fmt.Sprintf(format, v...))
+}
+
+// LogError internal, used in all packages
+func LogError(logType LogType, v ...interface{}) string {
+ if logType¤tLogType != 0 {
+ t := fmt.Sprintln(v...)
+ log.Print("ERROR: ", t)
+ return t
+ }
+ return ""
+}
+
+// LogWarning internal, used in all packages
+func LogWarning(logType LogType, v ...interface{}) {
+ if logType¤tLogType != 0 {
+ t := fmt.Sprintln(v...)
+ log.Print("WARNING: ", t)
+ }
+}
+
+// LogDebug internal, used in all packages
+func LogDebug(logType LogType, v ...interface{}) {
+ if logType¤tLogType != 0 {
+ t := fmt.Sprintln(v...)
+ log.Print("DEBUG: ", t)
+ }
+}
+
+// LogDrop internal, used in all packages
+func LogDrop(logType LogType, v ...interface{}) {
+ if logType¤tLogType != 0 {
+ t := fmt.Sprintln(v...)
+ log.Print("DROP: ", t)
+ }
+}
+
+// LogTitle internal, used in all packages
+func LogTitle(logType LogType, v ...interface{}) {
+ if logType¤tLogType != 0 {
+ log.Print(v...)
+ }
+}
+
+// SetLogType internal, used in flow package
+func SetLogType(logType LogType) {
+ log.SetFlags(0)
+ currentLogType = logType
+}
+
+// GetDPDKLogLevel internal, used in flow package
+func GetDPDKLogLevel() string {
+ switch currentLogType {
+ case No:
+ return "0"
+ case No | Initialization:
+ return "7"
+ case No | Initialization | Debug:
+ return "8"
+ case No | Initialization | Debug | Verbose:
+ return "8"
+ default:
+ return "8"
+ }
+}
diff --git a/dpdk/dpdk b/dpdk/dpdk
index 0da7f445..8b937bae 160000
--- a/dpdk/dpdk
+++ b/dpdk/dpdk
@@ -1 +1 @@
-Subproject commit 0da7f445df445630c794897347ee360d6fe6348b
+Subproject commit 8b937bae24a306ad82c0983c83feb1be23d41f13
diff --git a/dpdk/pktgen-dpdk b/dpdk/pktgen-dpdk
index 6a78a5b6..41995554 160000
--- a/dpdk/pktgen-dpdk
+++ b/dpdk/pktgen-dpdk
@@ -1 +1 @@
-Subproject commit 6a78a5b69a3d379c328fa3fbd5d2d259d99edd00
+Subproject commit 4199555481cd08fe08e32986c94e59836ca1cd4f
diff --git a/examples/.gitignore b/examples/.gitignore
index c60b8caa..e3c2f461 100644
--- a/examples/.gitignore
+++ b/examples/.gitignore
@@ -11,3 +11,5 @@ pingReplay
timer
netlink
devbind
+OSforwarding
+generate
diff --git a/examples/Dockerfile b/examples/Dockerfile
index dd089d3d..0ab249dc 100644
--- a/examples/Dockerfile
+++ b/examples/Dockerfile
@@ -19,3 +19,5 @@ COPY gtpu .
COPY pingReplay .
COPY timer .
COPY netlink .
+COPY generate .
+COPY OSforwarding .
diff --git a/examples/Makefile b/examples/Makefile
index 78fe0fa0..2a305c51 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -5,9 +5,10 @@
PATH_TO_MK = ../mk
IMAGENAME = nff-go-examples
EXECUTABLES = dump clonablePcapDumper kni copy errorHandling timer \
- createPacket sendFixedPktsNumber gtpu pingReplay \
- netlink gopacketParserExample devbind
-SUBDIRS = tutorial antiddos demo fileReadWrite firewall forwarding ipsec
+ createPacket sendFixedPktsNumber gtpu pingReplay \
+ netlink gopacketParserExample devbind generate \
+ OSforwarding
+SUBDIRS = tutorial antiddos demo fileReadWrite firewall forwarding ipsec lb
.PHONY: dpi nffPktgen
dpi:
diff --git a/examples/OSforwarding.go b/examples/OSforwarding.go
new file mode 100644
index 00000000..a845e160
--- /dev/null
+++ b/examples/OSforwarding.go
@@ -0,0 +1,24 @@
+// Copyright 2017 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "flag"
+ "github.com/intel-go/nff-go/flow"
+)
+
+func main() {
+ inport := flag.String("in", "", "device for receiver")
+ outport := flag.String("out", "", "device for sender")
+ flag.Parse()
+
+ flow.CheckFatal(flow.SystemInit(nil))
+
+ inputFlow, err := flow.SetReceiverOS(*inport)
+ flow.CheckFatal(err)
+ flow.CheckFatal(flow.SetSenderOS(inputFlow, *outport))
+
+ flow.CheckFatal(flow.SystemStart())
+}
diff --git a/examples/antiddos/antiDDoS.go b/examples/antiddos/antiDDoS.go
index 42d8e5e0..c01bf8eb 100644
--- a/examples/antiddos/antiDDoS.go
+++ b/examples/antiddos/antiDDoS.go
@@ -23,9 +23,9 @@ import (
"sync/atomic"
"time"
- "github.com/intel-go/nff-go/common"
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
)
// Constants are taken from paper:
@@ -104,11 +104,11 @@ func getPacketHash(pkt *packet.Packet) uint32 {
if pktIPv4 != nil {
pktTCP, pktUDP, pktICMP = pkt.ParseAllKnownL4ForIPv4()
srcAddr = []byte{byte(pktIPv4.SrcAddr), byte(pktIPv4.SrcAddr >> 8), byte(pktIPv4.SrcAddr >> 16), byte(pktIPv4.SrcAddr >> 24)}
- srcAddrLen = common.IPv4AddrLen
+ srcAddrLen = types.IPv4AddrLen
} else if pktIPv6 != nil {
pktTCP, pktUDP, pktICMP = pkt.ParseAllKnownL4ForIPv6()
srcAddr = pktIPv6.SrcAddr[:]
- srcAddrLen = common.IPv6AddrLen
+ srcAddrLen = types.IPv6AddrLen
}
if pktTCP != nil {
diff --git a/examples/antiddos/generatorForAntiDDoS.go b/examples/antiddos/generatorForAntiDDoS.go
index d20a93dc..4fe3bbda 100644
--- a/examples/antiddos/generatorForAntiDDoS.go
+++ b/examples/antiddos/generatorForAntiDDoS.go
@@ -19,6 +19,7 @@ import (
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
)
const (
@@ -43,10 +44,10 @@ var (
// addresses imitating users sending non flood
// flooding user's addresses will be generated
- goodAddresses = [goodDataListSize]uint32{packet.SwapBytesUint32(1235),
- packet.SwapBytesUint32(980),
- packet.SwapBytesUint32(2405),
- packet.SwapBytesUint32(3540)}
+ goodAddresses = [goodDataListSize]types.IPv4Address{packet.SwapBytesIPv4Addr(1235),
+ packet.SwapBytesIPv4Addr(980),
+ packet.SwapBytesIPv4Addr(2405),
+ packet.SwapBytesIPv4Addr(3540)}
// ports corresponding to addresses of users sending non flood
goodPorts = [goodDataListSize]uint16{packet.SwapBytesUint16(1),
packet.SwapBytesUint16(2),
@@ -69,7 +70,7 @@ func main() {
exampleDoneEvent = sync.NewCond(&sync.Mutex{})
// Create first packet flow
- outputFlow, err := flow.SetFastGenerator(generatePacket, speed, nil)
+ outputFlow, _, err := flow.SetFastGenerator(generatePacket, speed, nil)
flow.CheckFatal(err)
flow.CheckFatal(flow.SetSender(outputFlow, uint16(*outPort)))
inputFlow, err := flow.SetReceiver(uint16(*inPort))
@@ -115,7 +116,7 @@ func main() {
// Function to use in generator
func generatePacket(pkt *packet.Packet, context flow.UserContext) {
- var address *uint32
+ var address *types.IPv4Address
var port *uint16
if pkt == nil {
@@ -141,7 +142,7 @@ func generatePacket(pkt *packet.Packet, context flow.UserContext) {
*port = goodPorts[indx]
atomic.AddUint64(&sentNonFlood, 1)
} else {
- *address = packet.SwapBytesUint32(uint32(sentPackets))
+ *address = packet.SwapBytesIPv4Addr(types.IPv4Address(sentPackets))
*port = packet.SwapBytesUint16(uint16(sentPackets))
}
@@ -170,7 +171,7 @@ func checkInputFlow(pkt *packet.Packet, context flow.UserContext) {
}
}
-func isSrcGood(srcAddr uint32, srcPort uint16) bool {
+func isSrcGood(srcAddr types.IPv4Address, srcPort uint16) bool {
for i := 0; i < goodDataListSize; i++ {
if srcAddr == goodAddresses[i] && srcPort == goodPorts[i] {
return true
diff --git a/examples/createPacket.go b/examples/createPacket.go
index db71af15..061f0474 100644
--- a/examples/createPacket.go
+++ b/examples/createPacket.go
@@ -30,11 +30,11 @@ func main() {
flow.CheckFatal(flow.SystemInit(&config))
// Create packets with speed at least 1000 packets/s
if *enablePacketFromByte == false {
- firstFlow, err = flow.SetFastGenerator(generatePacket, 1000, nil)
+ firstFlow, _, err = flow.SetFastGenerator(generatePacket, 1000, nil)
flow.CheckFatal(err)
} else {
buffer, _ = hex.DecodeString("00112233445501112131415108004500002ebffd00000406747a7f0000018009090504d2162e123456781234569050102000ffe60000")
- firstFlow, err = flow.SetFastGenerator(generatePacketFromByte, 1000, nil)
+ firstFlow, _, err = flow.SetFastGenerator(generatePacketFromByte, 1000, nil)
flow.CheckFatal(err)
}
// Send all generated packets to the output
diff --git a/examples/demo/demo.go b/examples/demo/demo.go
index 8791c621..e20e6ebe 100644
--- a/examples/demo/demo.go
+++ b/examples/demo/demo.go
@@ -28,7 +28,8 @@ func main() {
// Initialize NFF-GO library at 16 cores by default
config := flow.Config{
- CPUList: "0-15",
+ CPUList: "0-15",
+ NoPacketHeadChange: true,
}
flow.CheckFatal(flow.SystemInit(&config))
diff --git a/examples/dpi/main/handlers.go b/examples/dpi/main/handlers.go
index ac066a80..53d79202 100644
--- a/examples/dpi/main/handlers.go
+++ b/examples/dpi/main/handlers.go
@@ -7,10 +7,10 @@ import (
"hash/fnv"
"sync/atomic"
- "github.com/intel-go/nff-go/common"
"github.com/intel-go/nff-go/examples/dpi/pattern"
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
)
type localCounters struct {
@@ -83,7 +83,7 @@ func splitBy5Tuple(pkt *packet.Packet, context flow.UserContext) uint {
return pattern.TotalNumFlows - 1
}
if ip4 != nil {
- if ip4.NextProtoID != common.TCPNumber && ip4.NextProtoID != common.UDPNumber {
+ if ip4.NextProtoID != types.TCPNumber && ip4.NextProtoID != types.UDPNumber {
return pattern.TotalNumFlows - 1
}
hash.Write([]byte{ip4.NextProtoID})
@@ -93,7 +93,7 @@ func splitBy5Tuple(pkt *packet.Packet, context flow.UserContext) uint {
flow.CheckFatal(binary.Write(buf, binary.LittleEndian, ip4.DstAddr))
hash.Write(buf.Bytes())
} else if ip6 != nil {
- if ip6.Proto != common.TCPNumber && ip6.Proto != common.UDPNumber {
+ if ip6.Proto != types.TCPNumber && ip6.Proto != types.UDPNumber {
return pattern.TotalNumFlows - 1
}
flow.CheckFatal(binary.Write(hash, binary.BigEndian, ip6.Proto))
diff --git a/examples/dpi/pattern/Makefile b/examples/dpi/pattern/Makefile
index 56a177a8..a73799c3 100644
--- a/examples/dpi/pattern/Makefile
+++ b/examples/dpi/pattern/Makefile
@@ -3,7 +3,7 @@
# license that can be found in the LICENSE file.
PATH_TO_MK = ../../../mk
-IMAGENAME = dpi
+IMAGENAME = dpi-pattern
pattern:
go install $(GO_COMPILE_FLAGS)
diff --git a/examples/forwarding/forwarding.go b/examples/forwarding/forwarding.go
index e6b9cb3a..d747d96e 100644
--- a/examples/forwarding/forwarding.go
+++ b/examples/forwarding/forwarding.go
@@ -1,10 +1,13 @@
-// Copyright 2017 Intel Corporation.
+// Copyright 2017-2019 Intel Corporation.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
+ "flag"
+ "net"
+
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
)
@@ -13,10 +16,23 @@ var l3Rules *packet.L3Rules
// Main function for constructing packet processing graph.
func main() {
+ inport := flag.Uint("inport", 0, "Port for receiving packets.")
+ numflows := flag.Uint("numflows", 5, "Number of output flows to use. First flow with number zero is used for dropped packets.")
+ nostats := flag.Bool("nostats", false, "Disable statics HTTP server.")
+ flag.Parse()
+
var err error
+ var statsServerAddres *net.TCPAddr = nil
+ if !*nostats {
+ // Set up address for stats web server
+ statsServerAddres = &net.TCPAddr{
+ Port: 8080,
+ }
+ }
+
// Initialize NFF-GO library at 16 cores by default
config := flow.Config{
- CPUList: "0-15",
+ StatsHTTPAddress: statsServerAddres,
}
flow.CheckFatal(flow.SystemInit(&config))
@@ -25,11 +41,11 @@ func main() {
flow.CheckFatal(err)
// Receive packets from zero port. Receive queue will be added automatically.
- inputFlow, err := flow.SetReceiver(0)
+ inputFlow, err := flow.SetReceiver(uint16(*inport))
flow.CheckFatal(err)
// Split packet flow based on ACL.
- flowsNumber := uint16(5)
+ flowsNumber := uint16(*numflows)
outputFlows, err := flow.SetSplitter(inputFlow, l3Splitter, uint(flowsNumber), nil)
flow.CheckFatal(err)
diff --git a/examples/generate.go b/examples/generate.go
new file mode 100644
index 00000000..336f9f4f
--- /dev/null
+++ b/examples/generate.go
@@ -0,0 +1,70 @@
+// Copyright 2017 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "github.com/intel-go/nff-go/flow"
+ "github.com/intel-go/nff-go/packet"
+ "time"
+)
+
+func main() {
+ mode := flag.Int("mode", 2, "mode of generating:\n0 - fast generate that will be slowed in a second.\n1 - time-based generate send by 32 packets.\n2 - time-based generate send by 1 packet.")
+ output := flag.Int("port", 1, "output port")
+ flag.Parse()
+ outputPort := uint16(*output)
+
+ flow.SystemInit(nil)
+
+ switch *mode {
+ case 0:
+ firstFlow, genChannel, _ := flow.SetFastGenerator(generatePacket, 3500, nil)
+ flow.CheckFatal(flow.SetSender(firstFlow, outputPort))
+ go updateSpeed(genChannel)
+ flow.SystemStart()
+ case 1:
+ firstFlow := flow.SetGenerator(generatePacket1, nil)
+ flow.CheckFatal(flow.SetSender(firstFlow, outputPort))
+ flow.SystemStart()
+ case 2:
+ temp, _ := (flow.SetReceiver(outputPort))
+ flow.SetStopper(temp)
+ flow.SystemInitPortsAndMemory()
+ generatePacket2(outputPort)
+ }
+}
+
+func generatePacket(pkt *packet.Packet, context flow.UserContext) {
+ packet.InitEmptyIPv4Packet(pkt, 1300)
+ pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}
+}
+
+func generatePacket1(pkt *packet.Packet, context flow.UserContext) {
+ packet.InitEmptyIPv4Packet(pkt, 1300)
+ pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}
+ time.Sleep(175 * time.Microsecond)
+}
+
+func generatePacket2(port uint16) {
+ for {
+ pkt, _ := packet.NewPacket()
+ packet.InitEmptyIPv4Packet(pkt, 1300)
+ pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}
+ pkt.SendPacket(port)
+ time.Sleep(175 * time.Microsecond)
+ }
+}
+
+func updateSpeed(genChannel chan uint64) {
+ var load int
+ for {
+ // Can be file or any other source
+ if _, err := fmt.Scanf("%d", &load); err == nil {
+ genChannel <- uint64(load)
+ }
+ }
+}
diff --git a/examples/gtpu.go b/examples/gtpu.go
index b59f4dd7..d58f407c 100644
--- a/examples/gtpu.go
+++ b/examples/gtpu.go
@@ -6,9 +6,9 @@ package main
import (
"fmt"
- "github.com/intel-go/nff-go/common"
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
)
func main() {
@@ -29,7 +29,7 @@ func decap(current *packet.Packet, context flow.UserContext) bool {
current.ParseL3()
ipv4 := current.GetIPv4()
- if ipv4 == nil || ipv4.DstAddr != packet.BytesToIPv4(55, 66, 77, 88) {
+ if ipv4 == nil || ipv4.DstAddr != types.BytesToIPv4(55, 66, 77, 88) {
// reject with wrong IP
println("ERROR")
return false
@@ -76,10 +76,10 @@ func encap(current *packet.Packet, context flow.UserContext) bool {
ipv4.FragmentOffset = 0
ipv4.TimeToLive = 64
- ipv4.TotalLength = packet.SwapBytesUint16(uint16(length - common.EtherLen))
- ipv4.NextProtoID = common.UDPNumber
- ipv4.SrcAddr = packet.BytesToIPv4(11, 22, 33, 44)
- ipv4.DstAddr = packet.BytesToIPv4(55, 66, 77, 88)
+ ipv4.TotalLength = packet.SwapBytesUint16(uint16(length - types.EtherLen))
+ ipv4.NextProtoID = types.UDPNumber
+ ipv4.SrcAddr = types.BytesToIPv4(11, 22, 33, 44)
+ ipv4.DstAddr = types.BytesToIPv4(55, 66, 77, 88)
ipv4.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(ipv4))
current.ParseL4ForIPv4()
@@ -88,7 +88,7 @@ func encap(current *packet.Packet, context flow.UserContext) bool {
// construct udphdr
udp.SrcPort = packet.SwapUDPPortGTPU
udp.DstPort = packet.SwapUDPPortGTPU
- udp.DgramLen = uint16(length - common.EtherLen - common.IPv4MinLen)
+ udp.DgramLen = uint16(length - types.EtherLen - types.IPv4MinLen)
udp.DgramCksum = 0
return true
@@ -99,8 +99,8 @@ func generate(current *packet.Packet, context flow.UserContext) {
packet.InitEmptyIPv4TCPPacket(current, payload)
ipv4 := current.GetIPv4NoCheck()
tcp := current.GetTCPNoCheck()
- ipv4.SrcAddr = packet.BytesToIPv4(1, 2, 3, 4)
- ipv4.DstAddr = packet.BytesToIPv4(5, 6, 7, 8)
+ ipv4.SrcAddr = types.BytesToIPv4(1, 2, 3, 4)
+ ipv4.DstAddr = types.BytesToIPv4(5, 6, 7, 8)
tcp.SrcPort = packet.SwapBytesUint16(111)
tcp.DstPort = packet.SwapBytesUint16(222)
}
diff --git a/examples/ipsec/ipsec_kernel.go b/examples/ipsec/ipsec_kernel.go
index 46e312be..1fbc361f 100644
--- a/examples/ipsec/ipsec_kernel.go
+++ b/examples/ipsec/ipsec_kernel.go
@@ -7,7 +7,7 @@ package ipsec
import "github.com/intel-go/nff-go/packet"
import "github.com/intel-go/nff-go/flow"
-import "github.com/intel-go/nff-go/common"
+import "github.com/intel-go/nff-go/types"
import "bytes"
import "unsafe"
import "crypto/aes"
@@ -17,8 +17,8 @@ const mode1234 = 1234
const espHeadLen = 24
const authLen = 12
const espTailLen = authLen + 2
-const etherLen = common.EtherLen
-const outerIPLen = common.IPv4MinLen
+const etherLen = types.EtherLen
+const outerIPLen = types.IPv4MinLen
type espHeader struct {
SPI uint32
@@ -40,8 +40,8 @@ func Decapsulation(currentPacket *packet.Packet, context flow.UserContext) bool
// Security Association
switch packet.SwapBytesUint32(currentESPHeader.SPI) {
case mode1234:
- encryptionPart := (*[common.MaxLength]byte)(unsafe.Pointer(currentPacket.StartAtOffset(0)))[etherLen+outerIPLen+espHeadLen : length-authLen]
- authPart := (*[common.MaxLength]byte)(unsafe.Pointer(currentPacket.StartAtOffset(0)))[etherLen+outerIPLen : length-authLen]
+ encryptionPart := (*[types.MaxLength]byte)(unsafe.Pointer(currentPacket.StartAtOffset(0)))[etherLen+outerIPLen+espHeadLen : length-authLen]
+ authPart := (*[types.MaxLength]byte)(unsafe.Pointer(currentPacket.StartAtOffset(0)))[etherLen+outerIPLen : length-authLen]
if decapsulationSPI123(authPart, currentESPTail.Auth, currentESPHeader.IV, encryptionPart, context) == false {
return false
}
@@ -82,8 +82,8 @@ func VectorEncapsulation(currentPackets []*packet.Packet, mask *[32]bool, notDro
currentPackets[i].EncapsulateHead(etherLen, outerIPLen+espHeadLen)
currentPackets[i].ParseL3()
ipv4 := currentPackets[i].GetIPv4NoCheck()
- ipv4.SrcAddr = packet.BytesToIPv4(111, 22, 3, 0)
- ipv4.DstAddr = packet.BytesToIPv4(3, 22, 111, 0)
+ ipv4.SrcAddr = types.BytesToIPv4(111, 22, 3, 0)
+ ipv4.DstAddr = types.BytesToIPv4(3, 22, 111, 0)
ipv4.VersionIhl = 0x45
ipv4.NextProtoID = esp
notDrop[i] = true
@@ -130,11 +130,11 @@ func vectorEncapsulationSPI123(currentPackets []*packet.Packet, n uint, context0
}
}
currentESPTail.paddingLen = paddingLength
- currentESPTail.nextIP = common.IPNumber
+ currentESPTail.nextIP = types.IPNumber
- context.vectorEncryptionPart[t] = (*[common.MaxLength]byte)(unsafe.Pointer(currentPackets[i+t].StartAtOffset(0)))[etherLen+outerIPLen+espHeadLen : newLength-authLen]
+ context.vectorEncryptionPart[t] = (*[types.MaxLength]byte)(unsafe.Pointer(currentPackets[i+t].StartAtOffset(0)))[etherLen+outerIPLen+espHeadLen : newLength-authLen]
context.vectorIV[t] = currentESPHeader.IV[:]
- context.vectorAuthPart[t] = (*[common.MaxLength]byte)(unsafe.Pointer(currentPackets[i+t].StartAtOffset(0)))[etherLen+outerIPLen : newLength-authLen]
+ context.vectorAuthPart[t] = (*[types.MaxLength]byte)(unsafe.Pointer(currentPackets[i+t].StartAtOffset(0)))[etherLen+outerIPLen : newLength-authLen]
context.vectorAuthPlace[t] = currentESPTail.Auth[:]
}
Encrypt(context.vectorEncryptionPart, context.vectorEncryptionPart, context.vectorIV, Z, context)
@@ -148,8 +148,8 @@ func ScalarEncapsulation(currentPacket *packet.Packet, context flow.UserContext)
currentPacket.ParseL3()
ipv4 := currentPacket.GetIPv4NoCheck()
- ipv4.SrcAddr = packet.BytesToIPv4(111, 22, 3, 0)
- ipv4.DstAddr = packet.BytesToIPv4(3, 22, 111, 0)
+ ipv4.SrcAddr = types.BytesToIPv4(111, 22, 3, 0)
+ ipv4.DstAddr = types.BytesToIPv4(3, 22, 111, 0)
ipv4.VersionIhl = 0x45
ipv4.NextProtoID = esp
@@ -180,16 +180,16 @@ func scalarEncapsulationSPI123(currentPacket *packet.Packet, context0 flow.UserC
}
}
currentESPTail.paddingLen = paddingLength
- currentESPTail.nextIP = common.IPNumber
+ currentESPTail.nextIP = types.IPNumber
// Encryption
- EncryptionPart := (*[common.MaxLength]byte)(currentPacket.StartAtOffset(0))[etherLen+outerIPLen+espHeadLen : newLength-authLen]
+ EncryptionPart := (*[types.MaxLength]byte)(currentPacket.StartAtOffset(0))[etherLen+outerIPLen+espHeadLen : newLength-authLen]
context.modeEnc.(SetIVer).SetIV(currentESPHeader.IV[:])
context.modeEnc.CryptBlocks(EncryptionPart, EncryptionPart)
// Authentication
context.mac123.Reset()
- AuthPart := (*[common.MaxLength]byte)(currentPacket.StartAtOffset(0))[etherLen+outerIPLen : newLength-authLen]
+ AuthPart := (*[types.MaxLength]byte)(currentPacket.StartAtOffset(0))[etherLen+outerIPLen : newLength-authLen]
context.mac123.Write(AuthPart)
copy(currentESPTail.Auth[:], context.mac123.Sum(nil))
}
diff --git a/examples/ipsec/perf/Makefile b/examples/ipsec/perf/Makefile
index 636e9002..7ceec28a 100644
--- a/examples/ipsec/perf/Makefile
+++ b/examples/ipsec/perf/Makefile
@@ -3,6 +3,6 @@
# license that can be found in the LICENSE file.
PATH_TO_MK = ../../../mk
-IMAGENAME = nff-go-examples
+IMAGENAME = nff-go-ipsec-perf
EXECUTABLES = ipsec
include $(PATH_TO_MK)/leaf.mk
diff --git a/examples/ipsec/stability/Makefile b/examples/ipsec/stability/Makefile
index 06952023..ba3c189e 100644
--- a/examples/ipsec/stability/Makefile
+++ b/examples/ipsec/stability/Makefile
@@ -3,6 +3,6 @@
# license that can be found in the LICENSE file.
PATH_TO_MK = ../../../mk
-IMAGENAME = nff-go-examples
+IMAGENAME = nff-go-ipsec-stability
EXECUTABLES = stability
include $(PATH_TO_MK)/leaf.mk
diff --git a/examples/ipsec/stability/stability.go b/examples/ipsec/stability/stability.go
index add0698c..32861850 100644
--- a/examples/ipsec/stability/stability.go
+++ b/examples/ipsec/stability/stability.go
@@ -4,6 +4,7 @@
package main
+import "github.com/intel-go/nff-go/types"
import "github.com/intel-go/nff-go/flow"
import "github.com/intel-go/nff-go/packet"
import "github.com/intel-go/nff-go/examples/ipsec"
@@ -45,18 +46,18 @@ func main() {
}
func gen(pkt *packet.Packet, context flow.UserContext) {
- packet.InitEmptyIPv4TCPPacket(pkt, 50)
- ipv4 := pkt.GetIPv4()
- tcp := pkt.GetTCPForIPv4()
+ packet.InitEmptyIPv4TCPPacket(pkt, 50)
+ ipv4 := pkt.GetIPv4()
+ tcp := pkt.GetTCPForIPv4()
- pkt.Ether.DAddr = [6]uint8{1,2,3,4,5,6}
- pkt.Ether.SAddr = [6]uint8{1,2,3,4,5,6}
+ pkt.Ether.DAddr = [6]uint8{1, 2, 3, 4, 5, 6}
+ pkt.Ether.SAddr = [6]uint8{1, 2, 3, 4, 5, 6}
- ipv4.SrcAddr = packet.BytesToIPv4(111,111,111,111)
- ipv4.DstAddr = packet.BytesToIPv4(222,222,222,222)
+ ipv4.SrcAddr = types.BytesToIPv4(111, 111, 111, 111)
+ ipv4.DstAddr = types.BytesToIPv4(222, 222, 222, 222)
- tcp.SrcPort = packet.SwapBytesUint16(25)
- tcp.DstPort = packet.SwapBytesUint16(35)
+ tcp.SrcPort = packet.SwapBytesUint16(25)
+ tcp.DstPort = packet.SwapBytesUint16(35)
step++
if step == 100 {
@@ -66,9 +67,9 @@ func gen(pkt *packet.Packet, context flow.UserContext) {
}
func dump_before(currentPacket *packet.Packet, context flow.UserContext) {
- fmt.Printf("Raw bytes before=%x\n", currentPacket.GetRawPacketBytes())
+ fmt.Printf("Raw bytes before=%x\n", currentPacket.GetRawPacketBytes())
}
func dump_after(currentPacket *packet.Packet, context flow.UserContext) {
- fmt.Printf("Raw bytes after =%x\n", currentPacket.GetRawPacketBytes())
+ fmt.Printf("Raw bytes after =%x\n", currentPacket.GetRawPacketBytes())
}
diff --git a/examples/kni.go b/examples/kni.go
index 83a77c53..b31f556c 100644
--- a/examples/kni.go
+++ b/examples/kni.go
@@ -18,9 +18,9 @@ package main
import (
"flag"
- "github.com/intel-go/nff-go/common"
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
)
var ping bool
@@ -80,11 +80,11 @@ func pingSeparator(current *packet.Packet, ctx flow.UserContext) bool {
if arp != nil {
return false
} else if ipv4 != nil {
- if ipv4.NextProtoID == common.ICMPNumber {
+ if ipv4.NextProtoID == types.ICMPNumber {
return false
}
} else if ipv6 != nil {
- if ipv6.Proto == common.ICMPNumber {
+ if ipv6.Proto == types.ICMPNumber {
return false
}
}
diff --git a/examples/lb/Makefile b/examples/lb/Makefile
new file mode 100644
index 00000000..4f53917c
--- /dev/null
+++ b/examples/lb/Makefile
@@ -0,0 +1,8 @@
+# Copyright 2018 Intel Corporation.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+PATH_TO_MK = ../../mk
+SUBDIRS = main
+
+include $(PATH_TO_MK)/intermediate.mk
diff --git a/examples/lb/balancer.go b/examples/lb/balancer.go
new file mode 100644
index 00000000..6aa78f00
--- /dev/null
+++ b/examples/lb/balancer.go
@@ -0,0 +1,163 @@
+// Copyright 2018 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lb
+
+import (
+ "crypto/sha256"
+ "fmt"
+
+ "github.com/intel-go/nff-go/flow"
+ "github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
+)
+
+func balancer(pkt *packet.Packet, ctx flow.UserContext) bool {
+ pkt.ParseL3()
+ originalProtocol := pkt.Ether.EtherType
+ var worker int
+
+ // Check packet protocol number
+ if originalProtocol == types.SwapARPNumber {
+ err := LBConfig.InputPort.neighCache.HandleIPv4ARPPacket(pkt)
+ if err != nil {
+ fmt.Println(err)
+ }
+ return false
+ } else if originalProtocol == types.SwapIPV4Number {
+ ipv4 := pkt.GetIPv4NoCheck()
+ if !LBConfig.TunnelSubnet.IPv4.CheckIPv4AddressWithinSubnet(ipv4.DstAddr) {
+ fmt.Println("Received IPv4 packet that is not targeted at balanced subnet",
+ LBConfig.TunnelPort.Subnet.IPv4.String(),
+ "it is targeted at address", ipv4.DstAddr.String(), "instead. Packet dropped.")
+ return false
+ }
+ worker = findWorkerIndexIPv4(pkt, ipv4)
+ } else if originalProtocol == types.SwapIPV6Number {
+ ipv6 := pkt.GetIPv6NoCheck()
+ if !LBConfig.TunnelSubnet.IPv6.CheckIPv6AddressWithinSubnet(ipv6.DstAddr) {
+ fmt.Println("Received IPv6 packet that is not targeted at balanced subnet",
+ LBConfig.TunnelPort.Subnet.IPv6.String(),
+ "it is targeted at address", ipv6.DstAddr.String(), "instead. Packet dropped.")
+ return false
+ }
+ worker = findWorkerIndexIPv6(pkt, ipv6)
+ } else {
+ return false
+ }
+
+ workerIP := LBConfig.WorkerAddresses[worker]
+ workerMAC, found := LBConfig.TunnelPort.neighCache.LookupMACForIPv4(workerIP)
+ if !found {
+ fmt.Println("Not found MAC address for IP", workerIP.String())
+ LBConfig.TunnelPort.neighCache.SendARPRequestForIPv4(workerIP, 0)
+ return false
+ }
+
+ if !pkt.EncapsulateHead(types.EtherLen, types.IPv4MinLen+types.GRELen) {
+ fmt.Println("EncapsulateHead returned error")
+ return false
+ }
+ pkt.ParseL3()
+
+ // Fill up L2
+ pkt.Ether.SAddr = LBConfig.TunnelPort.macAddress
+ pkt.Ether.DAddr = workerMAC
+ pkt.Ether.EtherType = types.SwapIPV4Number
+
+ // Fill up L3
+ ipv4 := pkt.GetIPv4NoCheck()
+ length := pkt.GetPacketLen()
+
+ // construct iphdr
+ ipv4.VersionIhl = 0x45
+ ipv4.TypeOfService = 0
+ ipv4.PacketID = 0x1513
+ ipv4.FragmentOffset = 0
+ ipv4.TimeToLive = 64
+
+ ipv4.TotalLength = packet.SwapBytesUint16(uint16(length - types.EtherLen))
+ ipv4.NextProtoID = types.GRENumber
+ ipv4.SrcAddr = LBConfig.TunnelPort.Subnet.IPv4.Addr
+ ipv4.DstAddr = workerIP
+ ipv4.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(ipv4))
+
+ // Fill up L4
+ pkt.ParseL4ForIPv4()
+ gre := pkt.GetGREForIPv4()
+ gre.Flags = 0
+ gre.NextProto = originalProtocol
+
+ return true
+}
+
+func findWorkerIndexIPv4(pkt *packet.Packet, ipv4 *packet.IPv4Hdr) int {
+ pkt.ParseL4ForIPv4()
+ hash := sha256.New()
+ sa := types.IPv4ToBytes(ipv4.SrcAddr)
+ hash.Write(sa[:])
+ protocol := ipv4.NextProtoID
+ switch protocol {
+ case types.TCPNumber:
+ tcp := pkt.GetTCPNoCheck()
+ sp, dp := portsToByteSlices(tcp.SrcPort, tcp.DstPort)
+ hash.Write(sp)
+ hash.Write(dp)
+ case types.UDPNumber:
+ udp := pkt.GetUDPNoCheck()
+ sp, dp := portsToByteSlices(udp.SrcPort, udp.DstPort)
+ hash.Write(sp)
+ hash.Write(dp)
+ case types.ICMPNumber:
+ icmp := pkt.GetICMPNoCheck()
+ id, _ := portsToByteSlices(icmp.Identifier, icmp.SeqNum)
+ hash.Write(id)
+ }
+ hash.Write([]byte{protocol})
+ da := types.IPv4ToBytes(ipv4.DstAddr)
+ hash.Write(da[:])
+
+ sum := hash.Sum(nil)
+ return int(sum[0]) % len(LBConfig.WorkerAddresses)
+}
+
+func findWorkerIndexIPv6(pkt *packet.Packet, ipv6 *packet.IPv6Hdr) int {
+ pkt.ParseL4ForIPv6()
+ hash := sha256.New()
+ sa := ipv6.SrcAddr
+ hash.Write(sa[:])
+ protocol := ipv6.Proto
+ switch protocol {
+ case types.TCPNumber:
+ tcp := pkt.GetTCPNoCheck()
+ sp, dp := portsToByteSlices(tcp.SrcPort, tcp.DstPort)
+ hash.Write(sp)
+ hash.Write(dp)
+ case types.UDPNumber:
+ udp := pkt.GetUDPNoCheck()
+ sp, dp := portsToByteSlices(udp.SrcPort, udp.DstPort)
+ hash.Write(sp)
+ hash.Write(dp)
+ case types.ICMPv6Number:
+ icmp := pkt.GetICMPNoCheck()
+ id, _ := portsToByteSlices(icmp.Identifier, icmp.SeqNum)
+ hash.Write(id)
+ }
+ hash.Write([]byte{protocol})
+ da := ipv6.DstAddr
+ hash.Write(da[:])
+
+ sum := hash.Sum(nil)
+ return int(sum[0]) % len(LBConfig.WorkerAddresses)
+}
+
+func portsToByteSlices(p1, p2 uint16) ([]byte, []byte) {
+ a1 := make([]byte, 2)
+ a1[0] = byte(p1 >> 8)
+ a1[1] = byte(p1)
+ a2 := make([]byte, 2)
+ a2[0] = byte(p2 >> 8)
+ a2[1] = byte(p2)
+ return a1, a2
+}
diff --git a/examples/lb/config.go b/examples/lb/config.go
new file mode 100644
index 00000000..b4042267
--- /dev/null
+++ b/examples/lb/config.go
@@ -0,0 +1,68 @@
+// Copyright 2018 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lb
+
+import (
+ "encoding/json"
+ "os"
+
+ "github.com/intel-go/nff-go/flow"
+ "github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
+)
+
+type NetworkSubnet struct {
+ IPv4 types.IPv4Subnet `json:"ipv4"`
+ IPv6 types.IPv6Subnet `json:"ipv6"`
+}
+
+type IpPort struct {
+ Index uint16 `json:"index"`
+ Subnet NetworkSubnet `json:"subnet"`
+ neighCache *packet.NeighboursLookupTable
+ macAddress types.MACAddress
+}
+
+type LoadBalancerConfig struct {
+ InputPort IpPort `json:"input-port"`
+ TunnelPort IpPort `json:"tunnel-port"`
+ TunnelSubnet NetworkSubnet `json:"tunnel-subnet"`
+ WorkerAddresses []types.IPv4Address `json:"worker-addresses"`
+}
+
+var LBConfig LoadBalancerConfig
+
+func ReadConfig(fileName string) error {
+ file, err := os.Open(fileName)
+ if err != nil {
+ return err
+ }
+ decoder := json.NewDecoder(file)
+
+ err = decoder.Decode(&LBConfig)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func InitFlows() {
+ ioFlow, err := flow.SetReceiver(LBConfig.InputPort.Index)
+ flow.CheckFatal(err)
+ flow.CheckFatal(flow.SetHandlerDrop(ioFlow, balancer, nil))
+ flow.CheckFatal(flow.SetSender(ioFlow, LBConfig.TunnelPort.Index))
+ ioFlow, err = flow.SetReceiver(LBConfig.TunnelPort.Index)
+ flow.CheckFatal(flow.SetHandlerDrop(ioFlow, arpHandler, nil))
+ flow.CheckFatal(flow.SetStopper(ioFlow))
+
+ LBConfig.InputPort.initPort()
+ LBConfig.TunnelPort.initPort()
+}
+
+func (port *IpPort) initPort() {
+ port.macAddress = flow.GetPortMACAddress(port.Index)
+ port.neighCache = packet.NewNeighbourTable(port.Index, port.macAddress, port.Subnet.IPv4.Addr, port.Subnet.IPv6.Addr)
+}
diff --git a/examples/lb/main/.gitignore b/examples/lb/main/.gitignore
new file mode 100644
index 00000000..aa1a077b
--- /dev/null
+++ b/examples/lb/main/.gitignore
@@ -0,0 +1 @@
+lb
diff --git a/examples/nffPktgen/perfTest/Dockerfile b/examples/lb/main/Dockerfile
similarity index 86%
rename from examples/nffPktgen/perfTest/Dockerfile
rename to examples/lb/main/Dockerfile
index 170a9213..7fb3c943 100644
--- a/examples/nffPktgen/perfTest/Dockerfile
+++ b/examples/lb/main/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2017 Intel Corporation.
+# Copyright 2019 Intel Corporation.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
@@ -8,4 +8,6 @@ FROM ${USER_NAME}/nff-go-base
LABEL RUN docker run -it --privileged -v /sys/bus/pci/drivers:/sys/bus/pci/drivers -v /sys/kernel/mm/hugepages:/sys/kernel/mm/hugepages -v /sys/devices/system/node:/sys/devices/system/node -v /dev:/dev --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE
WORKDIR /workdir
-COPY perfTest .
+
+COPY lb .
+COPY config.json .
diff --git a/examples/nffPktgen/sendGetBack/Makefile b/examples/lb/main/Makefile
similarity index 63%
rename from examples/nffPktgen/sendGetBack/Makefile
rename to examples/lb/main/Makefile
index 48b152d5..7a3f7af2 100644
--- a/examples/nffPktgen/sendGetBack/Makefile
+++ b/examples/lb/main/Makefile
@@ -1,9 +1,11 @@
-# Copyright 2017 Intel Corporation.
+# Copyright 2018 Intel Corporation.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
PATH_TO_MK = ../../../mk
-IMAGENAME = nff-pktgen
-EXECUTABLES = sendGetBack
+IMAGENAME = lb
+EXECUTABLES = lb
+
+lb: lb.go ../config.go
include $(PATH_TO_MK)/leaf.mk
diff --git a/examples/lb/main/config-aws.json b/examples/lb/main/config-aws.json
new file mode 100644
index 00000000..06c80121
--- /dev/null
+++ b/examples/lb/main/config-aws.json
@@ -0,0 +1,24 @@
+{
+ "input-port": {
+ "index": 0,
+ "subnet": {
+ "ipv4": "10.0.14.10/24",
+ "ipv6": "2600:1f16:80:ad14::10/64"
+ }
+ },
+ "tunnel-port": {
+ "index": 1,
+ "subnet": {
+ "ipv4": "10.0.16.10/24",
+ "ipv6": "2600:1f16:80:ad16::10/64"
+ }
+ },
+ "tunnel-subnet": {
+ "ipv4": "10.0.18.0/24",
+ "ipv6": "2600:1f16:80:ad18::/64"
+ },
+ "worker-addresses": [
+ "10.0.16.20",
+ "10.0.16.30"
+ ]
+}
diff --git a/examples/lb/main/config.json b/examples/lb/main/config.json
new file mode 100644
index 00000000..e7813bd3
--- /dev/null
+++ b/examples/lb/main/config.json
@@ -0,0 +1,24 @@
+{
+ "input-port": {
+ "index": 0,
+ "subnet": {
+ "ipv4": "192.168.14.1/24",
+ "ipv6": "fd14::1/64"
+ }
+ },
+ "tunnel-port": {
+ "index": 1,
+ "subnet": {
+ "ipv4": "192.168.16.1/24",
+ "ipv6": "fd16::1/64"
+ }
+ },
+ "tunnel-subnet": {
+ "ipv4": "192.168.18.0/24",
+ "ipv6": "fd18::/64"
+ },
+ "worker-addresses": [
+ "192.168.16.2",
+ "192.168.16.3"
+ ]
+}
diff --git a/examples/lb/main/lb.go b/examples/lb/main/lb.go
new file mode 100644
index 00000000..3a448201
--- /dev/null
+++ b/examples/lb/main/lb.go
@@ -0,0 +1,34 @@
+// Copyright 2018 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "flag"
+
+ "github.com/intel-go/nff-go/flow"
+
+ "github.com/intel-go/nff-go/examples/lb"
+)
+
+func main() {
+ cores := flag.String("cores", "", "Specify CPU cores to use.")
+ configFile := flag.String("config", "config.json", "Specify config file name.")
+ noscheduler := flag.Bool("no-scheduler", false, "Disable scheduler.")
+ dpdkLogLevel := flag.String("dpdk", "--log-level=0", "Passes an arbitrary argument to dpdk EAL.")
+ flag.Parse()
+
+ // Read config
+ flow.CheckFatal(lb.ReadConfig(*configFile))
+
+ nffgoconfig := flow.Config{
+ CPUList: *cores,
+ DPDKArgs: []string{*dpdkLogLevel},
+ DisableScheduler: *noscheduler,
+ }
+
+ flow.CheckFatal(flow.SystemInit(&nffgoconfig))
+ lb.InitFlows()
+ flow.CheckFatal(flow.SystemStart())
+}
diff --git a/examples/lb/util.go b/examples/lb/util.go
new file mode 100644
index 00000000..0e35ce70
--- /dev/null
+++ b/examples/lb/util.go
@@ -0,0 +1,27 @@
+// Copyright 2018 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lb
+
+import (
+ "fmt"
+
+ "github.com/intel-go/nff-go/flow"
+ "github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
+)
+
+func arpHandler(pkt *packet.Packet, ctx flow.UserContext) bool {
+ pkt.ParseL3()
+ protocol := pkt.Ether.EtherType
+
+ if protocol == types.SwapARPNumber {
+ err := LBConfig.TunnelPort.neighCache.HandleIPv4ARPPacket(pkt)
+ if err != nil {
+ fmt.Println(err)
+ }
+ return false
+ }
+ return true
+}
diff --git a/examples/netlink.go b/examples/netlink.go
index ff2a0269..b2002b72 100755
--- a/examples/netlink.go
+++ b/examples/netlink.go
@@ -13,6 +13,7 @@ import (
"github.com/intel-go/nff-go/common"
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
"golang.org/x/sys/unix"
"github.com/vishvananda/netlink"
@@ -24,10 +25,10 @@ var lpm *packet.LPM
// LPM binds ip with number and below
// is a struct to get ip by binded value
-var portToIP []uint32
+var portToIP []types.IPv4Address
// length of portToIp
-var lenP2IP uint32
+var lenP2IP types.IPv4Address
func main() {
inport := flag.Uint("inport", 0, "port for receiver")
@@ -59,23 +60,23 @@ func main() {
func handler(current *packet.Packet, ctx flow.UserContext) {
ipv4, _, _ := current.ParseAllKnownL3()
if ipv4 != nil {
- var next uint32
+ var next types.IPv4Address
if lpm.Lookup(ipv4.DstAddr, &next) {
- common.LogDebug(common.Debug, "gateway for packet: ", packet.IPv4ToBytes(portToIP[next]))
+ common.LogDebug(common.Debug, "gateway for packet: ", types.IPv4ToBytes(portToIP[next]))
}
}
}
-func netToNffIPv4(netIP net.IP) uint32 {
+func netToNffIPv4(netIP net.IP) types.IPv4Address {
if netIP == nil || len(netIP) != 4 {
return 0
}
- return packet.BytesToIPv4(netIP[0], netIP[1], netIP[2], netIP[3])
+ return types.BytesToIPv4(netIP[0], netIP[1], netIP[2], netIP[3])
}
-func getIPAndDepth(netIP *net.IPNet) (uint32, uint8, error) {
+func getIPAndDepth(netIP *net.IPNet) (types.IPv4Address, uint8, error) {
var (
- ip uint32
+ ip types.IPv4Address
depth int
)
if netIP != nil {
diff --git a/examples/nffPktgen/Makefile b/examples/nffPktgen/Makefile
index 69366737..39d5fdcd 100644
--- a/examples/nffPktgen/Makefile
+++ b/examples/nffPktgen/Makefile
@@ -4,6 +4,6 @@
PATH_TO_MK = ../../mk
IMAGENAME = nff-pktgen
-SUBDIRS = sendGetBack perfTest
+SUBDIRS = testing
include $(PATH_TO_MK)/intermediate.mk
diff --git a/examples/nffPktgen/README.md b/examples/nffPktgen/README.md
index 8745a322..2a1d60f3 100644
--- a/examples/nffPktgen/README.md
+++ b/examples/nffPktgen/README.md
@@ -55,7 +55,7 @@ is a main generator nunction. Context is obligatory.
// check error
flow.CheckFatal(err)
// set generator
- outFlow, err := flow.SetFastGenerator(generator.Generate, speed, &context)
+ outFlow, _, err := flow.SetFastGenerator(generator.Generate, speed, &context)
// check error
flow.CheckFatal(err)
// send
diff --git a/examples/nffPktgen/generator/generator.go b/examples/nffPktgen/generator/generator.go
index d416e219..809685cd 100644
--- a/examples/nffPktgen/generator/generator.go
+++ b/examples/nffPktgen/generator/generator.go
@@ -5,262 +5,95 @@
package generator
import (
- "bytes"
- "encoding/binary"
"fmt"
- "math"
"math/rand"
- "os"
- "sync/atomic"
"unsafe"
- "github.com/intel-go/nff-go/common"
- "github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
)
-var gen generator
-
-type generator struct {
- count uint64
-}
-
-// GetGenerator returns generator struct pointer
-// generator is single and created only once
-func GetGenerator() *generator {
- return &gen
-}
-
-// GetGeneratedNumber returns a number of packets generated
-func (g *generator) GetGeneratedNumber() uint64 {
- return atomic.LoadUint64(&(g.count))
-}
-
-// ReadConfig function reads and parses config file.
-func ReadConfig(fileName string) ([]*MixConfig, error) {
- f, err := os.Open(fileName)
- if err != nil {
- return nil, fmt.Errorf("opening file failed with: %v ", err)
- }
- cfg, err := ParseConfig(f)
- if err != nil {
- return nil, fmt.Errorf("parsing config failed with: %v", err)
- }
- return cfg, nil
-}
-
-func addAddr(a *[]byte, b []byte) {
- var offset int
- aLen := len(*a)
- bLen := len(b)
- if aLen < bLen {
- add := make([]byte, bLen-aLen)
- *a = append(add, *a...)
- } else {
- offset = aLen - bLen
- }
- var next byte
- for i := bLen - 1; i >= 0; i-- {
- add := (*a)[i+offset] + b[i] + next
- if add > 255 {
- next = 1
- (*a)[i+offset] = byte(255) - add
- } else {
- (*a)[i+offset] = add
- next = 0
- }
- }
-}
-
-func getNextAddr(addr *AddrRange) []uint8 {
- addAddr(&(addr.Current), addr.Incr)
- // if current < min or current > max, copy min to current
- if bytes.Compare(addr.Current, addr.Min) < 0 || bytes.Compare(addr.Current, addr.Max) > 0 {
- copy(addr.Current, addr.Min)
- }
- return addr.Current
-}
-
-func copyAddr(destination []uint8, source []uint8, size int) {
- if size < len(source) {
- copy(destination[:], source[len(source)-size:])
- } else {
- copy(destination[size-len(source):], source[:])
+func getNextValue(addr *AddrRange) {
+ if addr.Inc == 0 {
+ return
}
-}
-
-func getNextPort(port *PortRange) (nextPort uint16) {
- if port.Current < port.Min || port.Current > port.Max {
- port.Current = port.Min
+ addr.Current += addr.Inc
+ if addr.Current > addr.Max {
+ addr.Current = addr.Min
+ } else if addr.Current < addr.Min {
+ addr.Current = addr.Max
}
- nextPort = port.Current
- port.Current += port.Incr
- return nextPort
}
-func getNextSeqNumber(seq *Sequence, rnd *rand.Rand) (nextSeqNum uint32) {
- nextSeqNum = seq.Next
+func getNextSeqNumber(seq *Sequence, rnd *rand.Rand) {
if seq.Type == RANDOM {
- seq.Next = rnd.Uint32()
+ seq.Current = rnd.Uint32()
} else if seq.Type == INCREASING {
- seq.Next++
+ seq.Current++
}
- return nextSeqNum
}
type dataCopier func(unsafe.Pointer, uint, *rand.Rand, unsafe.Pointer)
func copyRaw(configuration unsafe.Pointer, size uint, rnd *rand.Rand, copyTo unsafe.Pointer) {
- data := (*Raw)(configuration)
- copy((*[1 << 30]uint8)(copyTo)[0:size], ([]uint8(data.Data)))
+ data := (*string)(configuration)
+ copy((*[1 << 30]uint8)(copyTo)[0:size], ([]uint8(*data)))
}
func copyRand(configuration unsafe.Pointer, size uint, rnd *rand.Rand, copyTo unsafe.Pointer) {
- packetData := (*[1 << 30]byte)(copyTo)[0:size]
+ packetData := (*[1 << 30]uint64)(copyTo)[0 : size/8]
for i := range packetData {
- packetData[i] = byte(rnd.Int())
+ packetData[i] = rnd.Uint64()
+ }
+ tail := (*[1 << 30]byte)(copyTo)[size-size%8 : size]
+ for i := range tail {
+ tail[i] = byte(rnd.Uint64())
}
}
-func getDataSizeType(configuration unsafe.Pointer, dtype DataType, rnd *rand.Rand) (uint, unsafe.Pointer, dataCopier) {
- switch dtype {
+func getDataSizeType(configuration *RawBytes, rnd *rand.Rand) (uint, unsafe.Pointer, dataCopier) {
+ switch configuration.DType {
case RAWDATA:
- data := (*Raw)(configuration)
- return uint(len(data.Data)), configuration, copyRaw
+ return uint(len(configuration.Data)), unsafe.Pointer(&configuration.Data), copyRaw
case RANDDATA:
- data := (*RandBytes)(configuration)
- maxZise := data.Size + data.Deviation
+ data := configuration.Rand
+ maxSise := data.Size + data.Deviation
minSize := data.Size - data.Deviation
- randSize := uint(rnd.Float64()*float64(maxZise-minSize) + float64(minSize))
- return randSize, configuration, copyRand
+ randSize := uint(rnd.Float64()*float64(maxSise-minSize) + float64(minSize))
+ return randSize, unsafe.Pointer(uintptr(0)), copyRand
case PDISTDATA:
- data := (*[]PDistEntry)(configuration)
prob := 0.0
- rndN := math.Abs(rnd.Float64())
- maxProb := PDistEntry{Probability: 0}
- for _, item := range *data {
+ rndN := rnd.Float64()
+ for _, item := range configuration.Dist {
+ // Sum of all was checked to be 1
prob += item.Probability
if rndN <= prob {
- return getDataSizeType(item.Data, item.DType, rnd)
- }
- if item.Probability > maxProb.Probability {
- maxProb = item
+ return getDataSizeType1(item.Data, item.Rand, item.DType, rnd)
}
}
- if prob <= 0 || prob > 1 {
- panic(fmt.Sprintf("sum of pdist probabilities is invalid, %f", prob))
- }
- // get the variant with max prob
- // if something went wrong and rand did not match any prob
- // may happen if sum of prob was not 1
- return getDataSizeType(maxProb.Data, maxProb.DType, rnd)
}
panic(fmt.Sprintf("unknown data type"))
}
-func getGenerator(configuration *PacketConfig) (func(*packet.Packet, *PacketConfig, *rand.Rand), error) {
- switch configuration.DType {
- case ETHERHDR:
- l2 := (*EtherConfig)(configuration.Data)
- switch l2.DType {
- case IPHDR:
- l3 := (*IPConfig)(l2.Data)
- switch l3.DType {
- case TCPHDR:
- return generateTCPIP, nil
- case UDPHDR:
- return generateUDPIP, nil
- case ICMPHDR:
- return generateICMPIP, nil
- case RAWDATA, RANDDATA, PDISTDATA:
- return generateIP, nil
- default:
- return nil, fmt.Errorf("unknown packet l4 configuration")
- }
- case ARPHDR:
- return generateARP, nil
- case RAWDATA, RANDDATA, PDISTDATA:
- return generateEther, nil
- default:
- return nil, fmt.Errorf("unknown packet l3 configuration")
- }
- default:
- return nil, fmt.Errorf("unknown packet l2 configuration")
- }
-}
-
-// one unit for each mix
-type generatorTableUnit struct {
- have, need uint32
- generatorFunc func(*packet.Packet, *PacketConfig, *rand.Rand)
- config *PacketConfig
-}
-
-func (gtu *generatorTableUnit) String() string {
- return fmt.Sprintf("need: %d, config: %v\n", gtu.need, gtu.config)
-}
-
-type genParameters struct {
- table []generatorTableUnit
- next uint32
- length uint32
- rnd *rand.Rand
-}
-
-func (gp genParameters) Copy() interface{} {
- ret := new(genParameters)
- ret.table = make([]generatorTableUnit, len(gp.table))
- copy(ret.table, gp.table)
- ret.length = gp.length
- ret.rnd = rand.New(rand.NewSource(13))
- return ret
-}
-
-func (gp genParameters) Delete() {
-}
-
-// GetContext gets generator context according to config
-func GetContext(mixConfig []*MixConfig) (*genParameters, error) {
- var t []generatorTableUnit
- for _, packetConfig := range mixConfig {
- genFunc, err := getGenerator(packetConfig.Config)
- if err != nil {
- return nil, err
- }
- tu := generatorTableUnit{have: 0, need: packetConfig.Quantity, generatorFunc: genFunc, config: packetConfig.Config}
- t = append(t, tu)
- }
- ret := new(genParameters)
- ret.table = t
- ret.length = uint32(len(t))
- ret.rnd = rand.New(rand.NewSource(13))
- return ret, nil
-}
-
-// Generate is a main generatior func
-func Generate(pkt *packet.Packet, context flow.UserContext) {
- genP := context.(*genParameters)
- if genP.length > 1 {
- if genP.table[genP.next].have == genP.table[genP.next].need {
- genP.table[genP.next].have = 0
- if genP.next+1 < genP.length {
- genP.next++
- } else {
- genP.next = 0
- }
- }
+func getDataSizeType1(Data string, Rand RandBytes, DType DataType, rnd *rand.Rand) (uint, unsafe.Pointer, dataCopier) {
+ switch DType {
+ case RAWDATA:
+ return uint(len(Data)), unsafe.Pointer(&Data), copyRaw
+ case RANDDATA:
+ maxSise := Rand.Size + Rand.Deviation
+ minSize := Rand.Size - Rand.Deviation
+ randSize := uint(rnd.Float64()*float64(maxSise-minSize) + float64(minSize))
+ return randSize, unsafe.Pointer(uintptr(0)), copyRand
}
- genP.table[genP.next].generatorFunc(pkt, genP.table[genP.next].config, genP.rnd)
- atomic.AddUint64(&(gen.count), 1)
- genP.table[genP.next].have++
+ panic(fmt.Sprintf("unknown data type"))
}
func generateEther(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
if pkt == nil {
panic("Failed to create new packet")
}
- l2 := (*EtherConfig)(config.Data)
- size, dataConfig, copyDataFunc := getDataSizeType(l2.Data, l2.DType, rnd)
+ l2 := &config.Ether
+ size, dataConfig, copyDataFunc := getDataSizeType(&l2.Bytes, rnd)
if !packet.InitEmptyPacket(pkt, size) {
panic(fmt.Sprintf("InitEmptyPacket failed"))
@@ -269,77 +102,63 @@ func generateEther(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
fillEtherHdr(pkt, l2)
}
-func generateIP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
+func generateIPv4(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
if pkt == nil {
panic("Failed to create new packet")
}
- l2 := (*EtherConfig)(config.Data)
- l3 := (*IPConfig)(l2.Data)
- size, dataConfig, copyDataFunc := getDataSizeType(l3.Data, l3.DType, rnd)
- if l3.Version == 4 {
- if !packet.InitEmptyIPv4Packet(pkt, size) {
- panic(fmt.Sprintf("InitEmptyIPv4Packet returned false"))
- }
- } else if l3.Version == 6 {
- if !packet.InitEmptyIPv6Packet(pkt, size) {
- panic(fmt.Sprintf("InitEmptyIPv6Packet returned false"))
- }
- } else {
- panic(fmt.Sprintf("fillPacketl3 failed, unknovn version %d", l3.Version))
+ l2 := &config.Ether
+ l3 := &l2.IPv4
+ size, dataConfig, copyDataFunc := getDataSizeType(&l3.Bytes, rnd)
+ //size, _, _ := getDataSizeType(&l3.Bytes, rnd)
+ //size := uint(22)
+ if !packet.InitEmptyIPv4Packet(pkt, size) {
+ panic(fmt.Sprintf("InitEmptyIPv4Packet returned false"))
}
copyDataFunc(dataConfig, size, rnd, pkt.Data)
fillEtherHdr(pkt, l2)
- fillIPHdr(pkt, l3)
- if l3.Version == 4 {
- pktIP := (*packet.IPv4Hdr)(pkt.L3)
- pktIP.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pktIP))
- }
-}
-
-func To4(addr []byte) []byte {
- if len(addr) > common.IPv4AddrLen {
- return addr[len(addr)-common.IPv4AddrLen:]
- }
- return addr
+ fillIPv4Hdr(pkt, l3)
+ pktIP := (*packet.IPv4Hdr)(pkt.L3)
+ pktIP.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pktIP))
}
func generateARP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
if pkt == nil {
panic("Failed to create new packet")
}
- l2 := (*EtherConfig)(config.Data)
- l3 := (*ARPConfig)(l2.Data)
- var SHA, THA [common.EtherAddrLen]uint8
- copyAddr(SHA[:], getNextAddr(&(l3.SHA)), common.EtherAddrLen)
- SPA := binary.LittleEndian.Uint32(To4(getNextAddr(&(l3.SPA))))
- switch l3.Operation {
- case packet.ARPRequest:
+ l2 := &config.Ether
+ l3 := &l2.ARP
+ var SHA, THA [types.EtherAddrLen]uint8
+ SHA = [types.EtherAddrLen]uint8{byte(l3.SHA.Current >> 40), byte(l3.SHA.Current >> 32), byte(l3.SHA.Current >> 24), byte(l3.SHA.Current >> 16), byte(l3.SHA.Current >> 8), byte(l3.SHA.Current)}
+ getNextValue(&l3.SHA)
+ SPA := packet.SwapBytesIPv4Addr(types.IPv4Address(l3.SPA.Current))
+ getNextValue(&l3.SPA)
+ if l3.Operation == packet.ARPRequest {
if l3.Gratuitous {
if !packet.InitGARPAnnouncementRequestPacket(pkt, SHA, SPA) {
panic(fmt.Sprintf("InitGARPAnnouncementRequestPacket returned false"))
}
} else {
- TPA := binary.LittleEndian.Uint32(To4(getNextAddr(&(l3.TPA))))
+ TPA := packet.SwapBytesIPv4Addr(types.IPv4Address(l3.TPA.Current))
+ getNextValue(&l3.TPA)
if !packet.InitARPRequestPacket(pkt, SHA, SPA, TPA) {
panic(fmt.Sprintf("InitARPRequestPacket returned false"))
}
}
- case packet.ARPReply:
+ } else { //packet.ARPReply
if l3.Gratuitous {
if !packet.InitGARPAnnouncementReplyPacket(pkt, SHA, SPA) {
panic(fmt.Sprintf("InitGARPAnnouncementReplyPacket returned false"))
}
} else {
- copyAddr(THA[:], getNextAddr(&(l3.THA)), common.EtherAddrLen)
- TPA := binary.LittleEndian.Uint32(To4(getNextAddr(&(l3.TPA))))
+ THA = [types.EtherAddrLen]uint8{byte(l3.THA.Current >> 40), byte(l3.THA.Current >> 32), byte(l3.THA.Current >> 24), byte(l3.THA.Current >> 16), byte(l3.THA.Current >> 8), byte(l3.THA.Current)}
+ getNextValue(&l3.THA)
+ TPA := packet.SwapBytesIPv4Addr(types.IPv4Address(l3.TPA.Current))
+ getNextValue(&l3.TPA)
if !packet.InitARPReplyPacket(pkt, SHA, THA, SPA, TPA) {
panic(fmt.Sprintf("InitARPReplyPacket returned false"))
}
}
- default:
- panic(fmt.Sprintf("unsupported operation code: %d", l3.Operation))
}
- copyAddr(pkt.Ether.DAddr[:], getNextAddr(&(l2.DAddr)), common.EtherAddrLen)
if l2.VLAN != nil {
if !pkt.AddVLANTag(l2.VLAN.TCI) {
panic("failed to add vlan tag to arp packet")
@@ -347,120 +166,90 @@ func generateARP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
}
}
-func generateTCPIP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
+func generateTCPIPv4(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
if pkt == nil {
panic("Failed to create new packet")
}
- l2 := (*EtherConfig)(config.Data)
- l3 := (*IPConfig)(l2.Data)
- l4 := (*TCPConfig)(l3.Data)
- size, dataConfig, copyDataFunc := getDataSizeType(l4.Data, l4.DType, rnd)
- if l3.Version == 4 {
- if !packet.InitEmptyIPv4TCPPacket(pkt, size) {
- panic(fmt.Sprintf("InitEmptyIPv4TCPPacket returned false"))
- }
- } else if l3.Version == 6 {
- if !packet.InitEmptyIPv6TCPPacket(pkt, size) {
- panic(fmt.Sprintf("InitEmptyIPv6TCPPacket returned false"))
- }
- } else {
- panic(fmt.Sprintf("fill packet l4 failed, unknovn version %d", l3.Version))
+ l2 := &config.Ether
+ l3 := &l2.IPv4
+ l4 := &l3.TCP
+ size, dataConfig, copyDataFunc := getDataSizeType(&l4.Bytes, rnd)
+ if !packet.InitEmptyIPv4TCPPacket(pkt, size) {
+ panic(fmt.Sprintf("InitEmptyIPv4TCPPacket returned false"))
}
copyDataFunc(dataConfig, size, rnd, pkt.Data)
fillEtherHdr(pkt, l2)
- fillIPHdr(pkt, l3)
+ fillIPv4Hdr(pkt, l3)
fillTCPHdr(pkt, l4, rnd)
pktTCP := (*packet.TCPHdr)(pkt.L4)
- if l3.Version == 4 {
- pktIP := (*packet.IPv4Hdr)(pkt.L3)
- pktIP.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pktIP))
- pktTCP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv4TCPChecksum(pktIP, pktTCP, pkt.Data))
- } else if l3.Version == 6 {
- pktIP := (*packet.IPv6Hdr)(pkt.L3)
- pktTCP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv6TCPChecksum(pktIP, pktTCP, pkt.Data))
- }
+ pktIP := (*packet.IPv4Hdr)(pkt.L3)
+ pktIP.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pktIP))
+ pktTCP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv4TCPChecksum(pktIP, pktTCP, pkt.Data))
}
-func generateUDPIP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
+func generateUDPIPv4(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
if pkt == nil {
panic("Failed to create new packet")
}
- l2 := (*EtherConfig)(config.Data)
- l3 := (*IPConfig)(l2.Data)
- l4 := (*UDPConfig)(l3.Data)
- size, dataConfig, copyDataFunc := getDataSizeType(l4.Data, l4.DType, rnd)
- if l3.Version == 4 {
- if !packet.InitEmptyIPv4UDPPacket(pkt, size) {
- panic(fmt.Sprintf("InitEmptyIPv4UDPPacket returned false"))
- }
- } else if l3.Version == 6 {
- if !packet.InitEmptyIPv6UDPPacket(pkt, size) {
- panic(fmt.Sprintf("InitEmptyIPv6UDPPacket returned false"))
- }
- } else {
- panic(fmt.Sprintf("fill packet l4 failed, unknovn version %d", l3.Version))
+ l2 := &config.Ether
+ l3 := &l2.IPv4
+ l4 := &l3.UDP
+ size, dataConfig, copyDataFunc := getDataSizeType(&l4.Bytes, rnd)
+ if !packet.InitEmptyIPv4UDPPacket(pkt, size) {
+ panic(fmt.Sprintf("InitEmptyIPv4UDPPacket returned false"))
}
copyDataFunc(dataConfig, size, rnd, pkt.Data)
fillEtherHdr(pkt, l2)
- fillIPHdr(pkt, l3)
+ fillIPv4Hdr(pkt, l3)
fillUDPHdr(pkt, l4)
pktUDP := (*packet.UDPHdr)(pkt.L4)
- if l3.Version == 4 {
- pktIP := (*packet.IPv4Hdr)(pkt.L3)
- pktIP.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pktIP))
- pktUDP.DgramCksum = packet.SwapBytesUint16(packet.CalculateIPv4UDPChecksum(pktIP, pktUDP, pkt.Data))
- } else if l3.Version == 6 {
- pktIP := (*packet.IPv6Hdr)(pkt.L3)
- pktUDP.DgramCksum = packet.SwapBytesUint16(packet.CalculateIPv6UDPChecksum(pktIP, pktUDP, pkt.Data))
- }
+ pktIP := (*packet.IPv4Hdr)(pkt.L3)
+ pktIP.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pktIP))
+ pktUDP.DgramCksum = packet.SwapBytesUint16(packet.CalculateIPv4UDPChecksum(pktIP, pktUDP, pkt.Data))
}
-func generateICMPIP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
+func generateICMPIPv4(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
if pkt == nil {
panic("Failed to create new packet")
}
- l2 := (*EtherConfig)(config.Data)
- l3 := (*IPConfig)(l2.Data)
- l4 := (*ICMPConfig)(l3.Data)
- size, dataConfig, copyDataFunc := getDataSizeType(l4.Data, l4.DType, rnd)
- if l3.Version == 4 {
- if !packet.InitEmptyIPv4ICMPPacket(pkt, size) {
- panic(fmt.Sprintf("InitEmptyIPv4ICMPPacket returned false"))
- }
- } else if l3.Version == 6 {
- if !packet.InitEmptyIPv6ICMPPacket(pkt, size) {
- panic(fmt.Sprintf("InitEmptyIPv6ICMPPacket returned false"))
- }
- } else {
- panic(fmt.Sprintf("fill packet l4 failed, unknovn version %d", l3.Version))
+ l2 := &config.Ether
+ l3 := &l2.IPv4
+ l4 := &l3.ICMP
+ size, dataConfig, copyDataFunc := getDataSizeType(&l4.Bytes, rnd)
+ if !packet.InitEmptyIPv4ICMPPacket(pkt, size) {
+ panic(fmt.Sprintf("InitEmptyIPv4ICMPPacket returned false"))
}
copyDataFunc(dataConfig, size, rnd, pkt.Data)
fillEtherHdr(pkt, l2)
- fillIPHdr(pkt, l3)
+ fillIPv4Hdr(pkt, l3)
fillICMPHdr(pkt, l4, rnd)
pktICMP := (*packet.ICMPHdr)(pkt.L4)
- if l3.Version == 4 {
- pktIP := (*packet.IPv4Hdr)(pkt.L3)
- pktIP.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pktIP))
- pktICMP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv4ICMPChecksum(pktIP, pktICMP, pkt.Data))
- } else if l3.Version == 6 {
- pktIP := (*packet.IPv6Hdr)(pkt.L3)
- pktICMP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv6ICMPChecksum(pktIP, pktICMP, pkt.Data))
- }
+ pktIP := (*packet.IPv4Hdr)(pkt.L3)
+ pktIP.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pktIP))
+ pktICMP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv4ICMPChecksum(pktIP, pktICMP, pkt.Data))
}
func fillTCPHdr(pkt *packet.Packet, l4 *TCPConfig, rnd *rand.Rand) {
emptyPacketTCP := (*packet.TCPHdr)(pkt.L4)
- emptyPacketTCP.SrcPort = packet.SwapBytesUint16(getNextPort(&(l4.SPort)))
- emptyPacketTCP.DstPort = packet.SwapBytesUint16(getNextPort(&(l4.DPort)))
- emptyPacketTCP.SentSeq = packet.SwapBytesUint32(getNextSeqNumber((&l4.Seq), rnd))
+ emptyPacketTCP.SrcPort = packet.SwapBytesUint16(uint16(l4.SPort.Current))
+ emptyPacketTCP.DstPort = packet.SwapBytesUint16(uint16(l4.DPort.Current))
+ emptyPacketTCP.SentSeq = packet.SwapBytesUint32(l4.Seq.Current)
emptyPacketTCP.TCPFlags = l4.Flags
+ if l4.DPort.Inc != 0 {
+ getNextValue(&l4.DPort)
+ }
+ if l4.SPort.Inc != 0 {
+ getNextValue(&l4.SPort)
+ }
+ getNextSeqNumber(&l4.Seq, rnd)
}
func fillUDPHdr(pkt *packet.Packet, l4 *UDPConfig) {
emptyPacketUDP := (*packet.UDPHdr)(pkt.L4)
- emptyPacketUDP.SrcPort = packet.SwapBytesUint16(getNextPort(&(l4.SPort)))
- emptyPacketUDP.DstPort = packet.SwapBytesUint16(getNextPort(&(l4.DPort)))
+ emptyPacketUDP.SrcPort = packet.SwapBytesUint16(uint16(l4.SPort.Current))
+ emptyPacketUDP.DstPort = packet.SwapBytesUint16(uint16(l4.DPort.Current))
+ getNextValue(&l4.DPort)
+ getNextValue(&l4.SPort)
}
func fillICMPHdr(pkt *packet.Packet, l4 *ICMPConfig, rnd *rand.Rand) {
@@ -468,27 +257,34 @@ func fillICMPHdr(pkt *packet.Packet, l4 *ICMPConfig, rnd *rand.Rand) {
emptyPacketICMP.Type = l4.Type
emptyPacketICMP.Code = l4.Code
emptyPacketICMP.Identifier = l4.Identifier
- emptyPacketICMP.SeqNum = packet.SwapBytesUint16(uint16(getNextSeqNumber(&(l4.Seq), rnd)))
+ emptyPacketICMP.SeqNum = packet.SwapBytesUint16(uint16(l4.Seq.Current))
+ getNextSeqNumber(&l4.Seq, rnd)
}
-func fillIPHdr(pkt *packet.Packet, l3 *IPConfig) {
- if l3.Version == 4 {
- pktIP := (*packet.IPv4Hdr)(pkt.L3)
- pktIP.SrcAddr = binary.LittleEndian.Uint32(To4(getNextAddr(&(l3.SAddr))))
- pktIP.DstAddr = binary.LittleEndian.Uint32(To4(getNextAddr(&(l3.DAddr))))
- return
- }
- pktIP := (*packet.IPv6Hdr)(pkt.L3)
- copyAddr(pktIP.SrcAddr[:], getNextAddr(&(l3.SAddr)), common.IPv6AddrLen)
- copyAddr(pktIP.DstAddr[:], getNextAddr(&(l3.DAddr)), common.IPv6AddrLen)
+func fillIPv4Hdr(pkt *packet.Packet, l3 *IPv4Config) {
+ pktIP := (*packet.IPv4Hdr)(pkt.L3)
+ pktIP.SrcAddr = packet.SwapBytesIPv4Addr(types.IPv4Address(l3.SAddr.Current))
+ pktIP.DstAddr = packet.SwapBytesIPv4Addr(types.IPv4Address(l3.DAddr.Current))
+ getNextValue(&l3.DAddr)
+ getNextValue(&l3.SAddr)
+}
+
+// SwapBytesUint32 swaps uint32 in Little Endian and Big Endian
+func SwapBytesUint64(x uint64) uint64 {
+ return ((x & 0x00000000000000ff) << 40) | ((x & 0x000000000000ff00) << 24) | ((x & 0x0000000000ff0000) << 8) |
+ ((x & 0x00000000ff000000) >> 8) | ((x & 0x0000ff0000000000) >> 40) | ((x & 0x000000ff00000000) >> 24)
}
func fillEtherHdr(pkt *packet.Packet, l2 *EtherConfig) {
if l2.VLAN != nil {
addVLAN(pkt, l2.VLAN.TCI)
}
- copyAddr(pkt.Ether.DAddr[:], getNextAddr(&(l2.DAddr)), common.EtherAddrLen)
- copyAddr(pkt.Ether.SAddr[:], getNextAddr(&(l2.SAddr)), common.EtherAddrLen)
+ t := pkt.Ether.EtherType
+ *(*uint64)(unsafe.Pointer(&pkt.Ether.DAddr[0])) = SwapBytesUint64(l2.DAddr.Current)
+ *(*uint64)(unsafe.Pointer(&pkt.Ether.SAddr[0])) = SwapBytesUint64(l2.SAddr.Current)
+ pkt.Ether.EtherType = t
+ getNextValue(&l2.DAddr)
+ getNextValue(&l2.SAddr)
}
// faster version of packet.AddVLANTag, can be used only
@@ -498,7 +294,7 @@ func addVLAN(pkt *packet.Packet, tag uint16) {
if !pkt.EncapsulateHead(0, 4) {
panic("failed to add vlan tag, EncapsulateHead returned false")
}
- pkt.Ether.EtherType = packet.SwapBytesUint16(common.VLANNumber)
+ pkt.Ether.EtherType = packet.SwapBytesUint16(types.VLANNumber)
vhdr := pkt.GetVLAN()
if vhdr == nil {
panic("failed to get vlan, GetVLAN returned nil")
diff --git a/examples/nffPktgen/generator/ipv6.go b/examples/nffPktgen/generator/ipv6.go
new file mode 100644
index 00000000..1448d1ba
--- /dev/null
+++ b/examples/nffPktgen/generator/ipv6.go
@@ -0,0 +1,308 @@
+// Copyright 2018 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package generator
+
+import (
+ "bytes"
+ "fmt"
+ "math/big"
+ "math/rand"
+ "net"
+ "strings"
+
+ "github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
+)
+
+func addAddr(a *[]byte, b []byte) {
+ var offset int
+ aLen := len(*a)
+ bLen := len(b)
+ if aLen < bLen {
+ add := make([]byte, bLen-aLen)
+ *a = append(add, *a...)
+ } else {
+ offset = aLen - bLen
+ }
+ var next byte
+ for i := bLen - 1; i >= 0; i-- {
+ add := (*a)[i+offset] + b[i] + next
+ if add > 255 {
+ next = 1
+ (*a)[i+offset] = byte(255) - add
+ } else {
+ (*a)[i+offset] = add
+ next = 0
+ }
+ }
+}
+
+func getNextAddr(addr *AddrIPv6Range) []uint8 {
+ addAddr(&(addr.Current), addr.Inc)
+ // if current < min or current > max, copy min to current
+ if bytes.Compare(addr.Current, addr.Min) < 0 || bytes.Compare(addr.Current, addr.Max) > 0 {
+ copy(addr.Current, addr.Min)
+ }
+ return addr.Current
+}
+
+func copyAddr(destination []uint8, source []uint8, size int) {
+ if size < len(source) {
+ copy(destination[:], source[len(source)-size:])
+ } else {
+ copy(destination[size-len(source):], source[:])
+ }
+}
+
+func generateIPv6(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
+ if pkt == nil {
+ panic("Failed to create new packet")
+ }
+ l2 := &config.Ether
+ l3 := &l2.IPv6
+ size, dataConfig, copyDataFunc := getDataSizeType(&l3.Bytes, rnd)
+ if !packet.InitEmptyIPv6Packet(pkt, size) {
+ panic(fmt.Sprintf("InitEmptyIPv6Packet returned false"))
+ }
+ copyDataFunc(dataConfig, size, rnd, pkt.Data)
+ fillEtherHdr(pkt, l2)
+ fillIPv6Hdr(pkt, l3)
+}
+
+func generateTCPIPv6(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
+ if pkt == nil {
+ panic("Failed to create new packet")
+ }
+ l2 := &config.Ether
+ l3 := &l2.IPv6
+ l4 := &l3.TCP
+ size, dataConfig, copyDataFunc := getDataSizeType(&l4.Bytes, rnd)
+ if !packet.InitEmptyIPv6TCPPacket(pkt, size) {
+ panic(fmt.Sprintf("InitEmptyIPv6TCPPacket returned false"))
+ }
+ copyDataFunc(dataConfig, size, rnd, pkt.Data)
+ fillEtherHdr(pkt, l2)
+ fillIPv6Hdr(pkt, l3)
+ fillTCPHdr(pkt, l4, rnd)
+ pktTCP := (*packet.TCPHdr)(pkt.L4)
+ pktIP := (*packet.IPv6Hdr)(pkt.L3)
+ pktTCP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv6TCPChecksum(pktIP, pktTCP, pkt.Data))
+}
+
+func generateUDPIPv6(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
+ if pkt == nil {
+ panic("Failed to create new packet")
+ }
+ l2 := &config.Ether
+ l3 := &l2.IPv6
+ l4 := &l3.UDP
+ size, dataConfig, copyDataFunc := getDataSizeType(&l4.Bytes, rnd)
+ if !packet.InitEmptyIPv6UDPPacket(pkt, size) {
+ panic(fmt.Sprintf("InitEmptyIPv6UDPPacket returned false"))
+ }
+ copyDataFunc(dataConfig, size, rnd, pkt.Data)
+ fillEtherHdr(pkt, l2)
+ fillIPv6Hdr(pkt, l3)
+ fillUDPHdr(pkt, l4)
+ pktUDP := (*packet.UDPHdr)(pkt.L4)
+ pktIP := (*packet.IPv6Hdr)(pkt.L3)
+ pktUDP.DgramCksum = packet.SwapBytesUint16(packet.CalculateIPv6UDPChecksum(pktIP, pktUDP, pkt.Data))
+}
+
+func generateICMPIPv6(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) {
+ if pkt == nil {
+ panic("Failed to create new packet")
+ }
+ l2 := &config.Ether
+ l3 := &l2.IPv6
+ l4 := &l3.ICMP
+ size, dataConfig, copyDataFunc := getDataSizeType(&l4.Bytes, rnd)
+ if !packet.InitEmptyIPv6ICMPPacket(pkt, size) {
+ panic(fmt.Sprintf("InitEmptyIPv6ICMPPacket returned false"))
+ }
+ copyDataFunc(dataConfig, size, rnd, pkt.Data)
+ fillEtherHdr(pkt, l2)
+ fillIPv6Hdr(pkt, l3)
+ fillICMPHdr(pkt, l4, rnd)
+ pktICMP := (*packet.ICMPHdr)(pkt.L4)
+ pktIP := (*packet.IPv6Hdr)(pkt.L3)
+ pktICMP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv6ICMPChecksum(pktIP, pktICMP, pkt.Data))
+}
+
+func fillIPv6Hdr(pkt *packet.Packet, l3 *IPv6Config) {
+ pktIP := (*packet.IPv6Hdr)(pkt.L3)
+ copyAddr(pktIP.SrcAddr[:], getNextAddr(&(l3.SAddr)), types.IPv6AddrLen)
+ copyAddr(pktIP.DstAddr[:], getNextAddr(&(l3.DAddr)), types.IPv6AddrLen)
+}
+
+// AddrRange describes range of addresses.
+type AddrIPv6Range struct {
+ Min []byte
+ Max []byte
+ Current []byte
+ Inc []byte
+}
+
+// IPv6Config configures ip header.
+type IPv6Config struct {
+ SAddr AddrIPv6Range // source address
+ DAddr AddrIPv6Range // destination address
+ DType DataType
+ TCP TCPConfig
+ UDP UDPConfig
+ ICMP ICMPConfig
+ Bytes RawBytes
+}
+
+func parseIPv6Hdr(in map[string]interface{}) (IPv6Config, error) {
+ ipHdr := IPv6Config{DAddr: AddrIPv6Range{}, SAddr: AddrIPv6Range{}}
+ for k, v := range in {
+ switch strings.ToLower(k) {
+ case "saddr":
+ saddr, err := parseIPv6Addr(v)
+ if err != nil {
+ return IPv6Config{}, fmt.Errorf("parseIPv6Addr for ip saddr returned: %v", err)
+ }
+ ipHdr.SAddr = saddr
+ case "daddr":
+ daddr, err := parseIPv6Addr(v)
+ if err != nil {
+ return IPv6Config{}, fmt.Errorf("parseIPv6Addr for ip daddr returned: %v", err)
+ }
+ ipHdr.DAddr = daddr
+ case "tcp":
+ tcpConf, err := parseTCPHdr(v.(map[string]interface{}))
+ if err != nil {
+ return IPv6Config{}, fmt.Errorf("parseTCPHdr returned %v", err)
+ }
+ ipHdr.TCP = tcpConf
+ ipHdr.DType = TCPHDR
+ break
+ case "udp":
+ udpConf, err := parseUDPHdr(v.(map[string]interface{}))
+ if err != nil {
+ return IPv6Config{}, fmt.Errorf("parseUDPHdr returned %v", err)
+ }
+ ipHdr.UDP = udpConf
+ ipHdr.DType = UDPHDR
+ break
+ case "icmp":
+ icmpConf, err := parseICMPHdr(v.(map[string]interface{}))
+ if err != nil {
+ return IPv6Config{}, fmt.Errorf("parseICMPHdr returned %v", err)
+ }
+ ipHdr.ICMP = icmpConf
+ ipHdr.DType = ICMPHDR
+ break
+ default:
+ data, err := parseData(map[string]interface{}{k: v})
+ if err != nil {
+ return IPv6Config{}, fmt.Errorf("parseData for ip returned: %v", err)
+ }
+ ipHdr.Bytes = data
+ ipHdr.DType = DATA
+ break
+ }
+ }
+ return ipHdr, nil
+}
+
+func parseRawIPv6Addr(rawAddr string) ([]uint8, error) {
+ addr := net.ParseIP(rawAddr)
+ if addr == nil {
+ return nil, fmt.Errorf("parsing ip addr could not parse address for %s", rawAddr)
+ }
+ return addr, nil
+}
+
+func parseIPv6Addr(value interface{}) (AddrIPv6Range, error) {
+ switch v2 := value.(type) {
+ case map[string]interface{}:
+ for k, v := range v2 {
+ switch strings.ToLower(k) {
+ case "range":
+ addrRange, err := parseAddrIPv6Range(v.(map[string]interface{}), parseRawIPv6Addr)
+ if err != nil {
+ return AddrIPv6Range{}, fmt.Errorf("parseAddrIPv6Range returned: %v", err)
+ }
+ return addrRange, nil
+ default:
+ return AddrIPv6Range{}, fmt.Errorf("unknown key in ip addr: %s", k)
+ }
+ }
+ case string:
+ saddr, err := parseRawIPv6Addr(v2)
+ if err != nil {
+ return AddrIPv6Range{}, fmt.Errorf("parsing ip addr returned: %v", err)
+ }
+ ret := AddrIPv6Range{}
+ ret.Min = make([]byte, len(saddr))
+ copy(ret.Min, saddr)
+ ret.Max = make([]byte, len(saddr))
+ copy(ret.Max, saddr)
+ ret.Current = make([]byte, len(saddr))
+ copy(ret.Current, saddr)
+ return ret, nil
+ }
+ return AddrIPv6Range{}, fmt.Errorf("unknown type")
+}
+
+type fn6 func(string) ([]uint8, error)
+
+func parseAddrIPv6Range(in map[string]interface{}, parseFunc fn6) (AddrIPv6Range, error) {
+ addr := AddrIPv6Range{}
+ wasMin, wasMax, wasStart, wasIncr := false, false, false, false
+ for k, v := range in {
+ switch strings.ToLower(k) {
+ case "min":
+ min, err := parseFunc(v.(string))
+ if err != nil {
+ return AddrIPv6Range{}, fmt.Errorf("parsing min returned: %v", err)
+ }
+ addr.Min = make([]byte, len(min))
+ copy(addr.Min, min)
+ wasMin = true
+ case "max":
+ max, err := parseFunc(v.(string))
+ if err != nil {
+ return AddrIPv6Range{}, fmt.Errorf("parsing max returned: %v", err)
+ }
+ addr.Max = make([]byte, len(max))
+ copy(addr.Max, max)
+ wasMax = true
+ case "start":
+ start, err := parseFunc(v.(string))
+ if err != nil {
+ return AddrIPv6Range{}, fmt.Errorf("parsing start returned: %v", err)
+ }
+ addr.Current = make([]byte, len(start))
+ copy(addr.Current, start)
+ wasStart = true
+ case "incr":
+ addr.Inc = big.NewInt((int64)(v.(float64))).Bytes()
+ wasIncr = true
+ default:
+ return AddrIPv6Range{}, fmt.Errorf("unknown key %s", k)
+ }
+ }
+ if !wasMax || !wasMin {
+ return AddrIPv6Range{}, fmt.Errorf("Min and max values should be given for range")
+ }
+ if bytes.Compare(addr.Max, addr.Min) < 0 {
+ return AddrIPv6Range{}, fmt.Errorf("Min value should be less than Max")
+ }
+ if !wasStart {
+ addr.Current = make([]byte, len(addr.Min))
+ copy(addr.Current, addr.Min)
+ }
+
+ if bytes.Compare(addr.Current, addr.Min) < 0 || bytes.Compare(addr.Current, addr.Max) > 0 {
+ return AddrIPv6Range{}, fmt.Errorf(fmt.Sprintf("Start value should be between min and max: start=%v, min=%v, max=%v", addr.Current, addr.Min, addr.Max))
+ }
+ if !wasIncr {
+ addr.Inc = []byte{1}
+ }
+ return addr, nil
+}
diff --git a/examples/nffPktgen/generator/parseConfig.go b/examples/nffPktgen/generator/parseConfig.go
index 84e7090f..f80cc154 100644
--- a/examples/nffPktgen/generator/parseConfig.go
+++ b/examples/nffPktgen/generator/parseConfig.go
@@ -6,48 +6,24 @@ package generator
import (
"bufio"
- "bytes"
"encoding/json"
"fmt"
- "math/big"
"math/rand"
"net"
"os"
"regexp"
"strings"
- "unsafe"
- "github.com/intel-go/nff-go/common"
+ "github.com/intel-go/nff-go/types"
)
var mixPattern = regexp.MustCompile(`^mix[0-9]*$`)
-// AddrRange describes range of addresses.
type AddrRange struct {
- Min []byte
- Max []byte
- Current []byte
- Incr []byte
-}
-
-func (ar *AddrRange) String() string {
- s := "addrRange:\n"
- s += fmt.Sprintf("min: %v, max: %v, start: %v, incr: %d", ar.Min, ar.Max, ar.Current, ar.Incr)
- return s
-}
-
-// PortRange describes range of ports.
-type PortRange struct {
- Min uint16
- Max uint16
- Current uint16
- Incr uint16
-}
-
-func (pr *PortRange) String() string {
- s := "portRange:\n"
- s += fmt.Sprintf("min: %v, max: %v, start: %v, incr: %d", pr.Min, pr.Max, pr.Current, pr.Incr)
- return s
+ Min uint64
+ Max uint64
+ Current uint64
+ Inc uint64
}
// SequenceType used in enum below.
@@ -61,19 +37,22 @@ const (
// Sequence contains type and next sequence value.
type Sequence struct {
- Type SequenceType
- Next uint32
+ Type SequenceType
+ Current uint32
}
type DataType int
const (
- ETHERHDR = iota
- IPHDR
+ NULL = iota
+ ETHERHDR
+ IPv4HDR
+ IPv6HDR
TCPHDR
UDPHDR
ICMPHDR
ARPHDR
+ DATA
PDISTDATA
RANDDATA
RAWDATA
@@ -83,17 +62,17 @@ const (
// PacketConfig configures packet
type PacketConfig struct {
DType DataType
- Data unsafe.Pointer
+ Ether EtherConfig
}
// MixConfig contains PacketConfigs with quantity.
type MixConfig struct {
- Config *PacketConfig
+ Config PacketConfig
Quantity uint32
}
func (mc *MixConfig) String() string {
- return fmt.Sprintf("config: %v; quantity: %v\n", *(mc.Config), mc.Quantity)
+ return fmt.Sprintf("config: %v; quantity: %v\n", mc.Config, mc.Quantity)
}
// EtherConfig configures ether header.
@@ -102,7 +81,10 @@ type EtherConfig struct {
SAddr AddrRange
VLAN *VlanTagConfig
DType DataType
- Data unsafe.Pointer
+ IPv4 IPv4Config
+ IPv6 IPv6Config
+ ARP ARPConfig
+ Bytes RawBytes
}
// VlanTagConfig configures vlan tag
@@ -110,31 +92,33 @@ type VlanTagConfig struct {
TCI uint16
}
-// IPConfig configures ip header.
-type IPConfig struct {
- Version int
- SAddr AddrRange // source address
- DAddr AddrRange // destination address
- DType DataType
- Data unsafe.Pointer
+// IPv4Config configures ip header.
+type IPv4Config struct {
+ SAddr AddrRange // source address
+ DAddr AddrRange // destination address
+ DType DataType
+ TCP TCPConfig
+ UDP UDPConfig
+ ICMP ICMPConfig
+ Bytes RawBytes
}
// TCPConfig configures tcp header.
type TCPConfig struct {
- SPort PortRange
- DPort PortRange
+ SPort AddrRange
+ DPort AddrRange
Seq Sequence
- Flags common.TCPFlags
+ Flags types.TCPFlags
DType DataType
- Data unsafe.Pointer
+ Bytes RawBytes
}
// UDPConfig configures tcp header.
type UDPConfig struct {
- SPort PortRange
- DPort PortRange
+ SPort AddrRange
+ DPort AddrRange
DType DataType
- Data unsafe.Pointer
+ Bytes RawBytes
}
// ICMPConfig configures tcp header.
@@ -144,7 +128,7 @@ type ICMPConfig struct {
Identifier uint16
Seq Sequence
DType DataType
- Data unsafe.Pointer
+ Bytes RawBytes
}
// ARPConfig configures arp header.
@@ -161,7 +145,8 @@ type ARPConfig struct {
type PDistEntry struct {
Probability float64
DType DataType
- Data unsafe.Pointer
+ Data string
+ Rand RandBytes
}
// RandBytes gives a payload of random bytes, of a given size.
@@ -172,12 +157,15 @@ type RandBytes struct {
}
// Raw represents raw data
-type Raw struct {
- Data string
+type RawBytes struct {
+ Data string
+ Rand RandBytes
+ Dist []PDistEntry
+ DType DataType
}
// ParseConfig parses json config and returns []*MixConfig.
-func ParseConfig(f *os.File) (config []*MixConfig, err error) {
+func ParseConfig(f *os.File) (config []MixConfig, err error) {
r := bufio.NewReader(f)
var in map[string]interface{}
err = json.NewDecoder(r).Decode(&in)
@@ -193,8 +181,8 @@ func ParseConfig(f *os.File) (config []*MixConfig, err error) {
if err != nil {
return nil, fmt.Errorf("parseEtherHdr returned: %v", err)
}
- pktConfig := &PacketConfig{Data: unsafe.Pointer(ðHdr), DType: ETHERHDR}
- return append(config, &MixConfig{Config: pktConfig, Quantity: 1}), nil
+ pktConfig := PacketConfig{Ether: ethHdr, DType: ETHERHDR}
+ return append(config, MixConfig{Config: pktConfig, Quantity: 1}), nil
case mixPattern.MatchString(key):
return ParseMixConfig(in)
default:
@@ -206,13 +194,13 @@ func ParseConfig(f *os.File) (config []*MixConfig, err error) {
}
// ParseMixConfig parses json config and returns []*MixConfig.
-func ParseMixConfig(in map[string]interface{}) (config []*MixConfig, err error) {
+func ParseMixConfig(in map[string]interface{}) (config []MixConfig, err error) {
for k, v := range in {
key := strings.ToLower(k)
switch {
case mixPattern.MatchString(key):
var (
- pktConfig *PacketConfig
+ pktConfig PacketConfig
q uint32
)
mixUnit := v.(map[string]interface{})
@@ -224,17 +212,17 @@ func ParseMixConfig(in map[string]interface{}) (config []*MixConfig, err error)
if err != nil {
return nil, fmt.Errorf("parseEtherHdr returned: %v", err)
}
- pktConfig = &PacketConfig{Data: unsafe.Pointer(ðHdr), DType: ETHERHDR}
+ pktConfig = PacketConfig{Ether: ethHdr, DType: ETHERHDR}
case "quantity", "q":
q = uint32(vv.(float64))
default:
return nil, fmt.Errorf("unexpected key: %s, expected ether and quantity or q", k)
}
}
- if q == 0 || pktConfig == nil {
+ if q == 0 || pktConfig.DType == NULL {
return nil, fmt.Errorf("some fields were not set")
}
- config = append(config, &MixConfig{Config: pktConfig, Quantity: q})
+ config = append(config, MixConfig{Config: pktConfig, Quantity: q})
default:
return nil, fmt.Errorf("unexpected key: %s, expected mix[0-9]*", k)
}
@@ -261,13 +249,21 @@ func parseEtherHdr(in map[string]interface{}) (EtherConfig, error) {
case "vlan-tci":
ethConfig.VLAN = &(VlanTagConfig{TCI: uint16(v.(float64))})
break
- case "ip":
- ipConf, err := parseIPHdr(v.(map[string]interface{}))
+ case "ipv4":
+ ipConf, err := parseIPv4Hdr(v.(map[string]interface{}))
if err != nil {
return EtherConfig{}, fmt.Errorf("parseIpHdr returned %v", err)
}
- ethConfig.Data = unsafe.Pointer(&ipConf)
- ethConfig.DType = IPHDR
+ ethConfig.IPv4 = ipConf
+ ethConfig.DType = IPv4HDR
+ break
+ case "ipv6":
+ ipConf, err := parseIPv6Hdr(v.(map[string]interface{}))
+ if err != nil {
+ return EtherConfig{}, fmt.Errorf("parseIpHdr returned %v", err)
+ }
+ ethConfig.IPv6 = ipConf
+ ethConfig.DType = IPv6HDR
break
case "arp":
arpConfig := v.(map[string]interface{})
@@ -275,104 +271,101 @@ func parseEtherHdr(in map[string]interface{}) (EtherConfig, error) {
if err != nil {
return EtherConfig{}, fmt.Errorf("parseARPHdr returned %v", err)
}
- ethConfig.Data = unsafe.Pointer(&arpConf)
+ ethConfig.ARP = arpConf
ethConfig.DType = ARPHDR
break
default:
- data, dataType, err := parseData(map[string]interface{}{k: v})
+ data, err := parseData(map[string]interface{}{k: v})
if err != nil {
return EtherConfig{}, fmt.Errorf("parseData for ether returned: %v", err)
}
- ethConfig.Data = data
- ethConfig.DType = dataType
+ ethConfig.Bytes = data
+ ethConfig.DType = DATA
break
}
}
return ethConfig, nil
}
-func parseData(in map[string]interface{}) (unsafe.Pointer, DataType, error) {
+func parseData(in map[string]interface{}) (ret RawBytes, err error) {
for k, v := range in {
switch strings.ToLower(k) {
case "raw":
- data, err := parseRaw(v.(map[string]interface{}))
+ ret.Data, err = parseRaw(v.(map[string]interface{}))
+ ret.DType = RAWDATA
if err != nil {
- return nil, NONE, fmt.Errorf("parseRaw returned %v", err)
+ return ret, fmt.Errorf("parseRaw returned %v", err)
}
- return unsafe.Pointer(&data), RAWDATA, nil
+ return ret, nil
case "randbytes":
- randBytes, err := parseRandBytes(v.(map[string]interface{}))
+ ret.Rand, err = parseRandBytes(v.(map[string]interface{}))
+ ret.DType = RANDDATA
if err != nil {
- return nil, NONE, fmt.Errorf("parseRandBytes returned %v", err)
+ return ret, fmt.Errorf("parseRandBytes returned %v", err)
}
- return unsafe.Pointer(&randBytes), RANDDATA, nil
+ return ret, nil
case "pdist":
- pdist, err := parsePdist(v.([]interface{}))
+ ret.Dist, err = parsePdist(v.([]interface{}))
+ ret.DType = PDISTDATA
if err != nil {
- return nil, NONE, fmt.Errorf("parsePdist returned %v", err)
+ return ret, fmt.Errorf("parsePdist returned %v", err)
}
- return unsafe.Pointer(&pdist), PDISTDATA, nil
+ return ret, nil
default:
fmt.Println("unknown key: ", k)
break
}
}
- return nil, NONE, fmt.Errorf("failed to parse data")
+ return ret, fmt.Errorf("failed to parse data")
}
-func parseIPHdr(in map[string]interface{}) (IPConfig, error) {
- ipHdr := IPConfig{Version: 4, DAddr: AddrRange{}, SAddr: AddrRange{}}
+func parseIPv4Hdr(in map[string]interface{}) (IPv4Config, error) {
+ ipHdr := IPv4Config{DAddr: AddrRange{}, SAddr: AddrRange{}}
for k, v := range in {
switch strings.ToLower(k) {
- case "version":
- version := (int)(v.(float64))
- if version != 4 && version != 6 {
- return IPConfig{}, fmt.Errorf("ip version should be 4 or 6, got: %d", version)
- }
- ipHdr.Version = version
case "saddr":
- saddr, err := parseIPAddr(v)
+ saddr, err := parseIPv4Addr(v)
if err != nil {
- return IPConfig{}, fmt.Errorf("parseIPAddr for ip saddr returned: %v", err)
+ return IPv4Config{}, fmt.Errorf("parseIPv4Addr for ip saddr returned: %v", err)
}
ipHdr.SAddr = saddr
case "daddr":
- daddr, err := parseIPAddr(v)
+ daddr, err := parseIPv4Addr(v)
if err != nil {
- return IPConfig{}, fmt.Errorf("parseIPAddr for ip daddr returned: %v", err)
+ return IPv4Config{}, fmt.Errorf("parseIPv4Addr for ip daddr returned: %v", err)
}
ipHdr.DAddr = daddr
case "tcp":
tcpConf, err := parseTCPHdr(v.(map[string]interface{}))
if err != nil {
- return IPConfig{}, fmt.Errorf("parseTCPHdr returned %v", err)
+ return IPv4Config{}, fmt.Errorf("parseTCPHdr returned %v", err)
}
- ipHdr.Data = unsafe.Pointer(&tcpConf)
+ ipHdr.TCP = tcpConf
ipHdr.DType = TCPHDR
break
case "udp":
udpConf, err := parseUDPHdr(v.(map[string]interface{}))
if err != nil {
- return IPConfig{}, fmt.Errorf("parseUDPHdr returned %v", err)
+ return IPv4Config{}, fmt.Errorf("parseUDPHdr returned %v", err)
}
- ipHdr.Data = unsafe.Pointer(&udpConf)
+ ipHdr.UDP = udpConf
ipHdr.DType = UDPHDR
break
case "icmp":
icmpConf, err := parseICMPHdr(v.(map[string]interface{}))
if err != nil {
- return IPConfig{}, fmt.Errorf("parseICMPHdr returned %v", err)
+ return IPv4Config{}, fmt.Errorf("parseICMPHdr returned %v", err)
}
- ipHdr.Data = unsafe.Pointer(&icmpConf)
+ ipHdr.ICMP = icmpConf
ipHdr.DType = ICMPHDR
break
default:
- data, dataType, err := parseData(map[string]interface{}{k: v})
+ data, err := parseData(map[string]interface{}{k: v})
if err != nil {
- return IPConfig{}, fmt.Errorf("parseData for ip returned: %v", err)
+ return IPv4Config{}, fmt.Errorf("parseData for ip returned: %v", err)
}
- ipHdr.Data = data
- ipHdr.DType = dataType
+ ipHdr.Bytes = data
+ ipHdr.DType = DATA
break
}
}
@@ -398,7 +391,7 @@ func parseARPHdr(in map[string]interface{}) (ARPConfig, error) {
}
arpHdr.SHA = sha
case "spa":
- spa, err := parseIPAddr(v)
+ spa, err := parseIPv4Addr(v)
if err != nil {
return ARPConfig{}, fmt.Errorf("parseIPAddr for spa returned: %v", err)
}
@@ -410,7 +403,7 @@ func parseARPHdr(in map[string]interface{}) (ARPConfig, error) {
}
arpHdr.THA = tha
case "tpa":
- tpa, err := parseIPAddr(v)
+ tpa, err := parseIPv4Addr(v)
if err != nil {
return ARPConfig{}, fmt.Errorf("parseIPAddr for tpa returned: %v", err)
}
@@ -423,7 +416,7 @@ func parseARPHdr(in map[string]interface{}) (ARPConfig, error) {
}
func parseTCPHdr(in map[string]interface{}) (TCPConfig, error) {
- tcpHdr := TCPConfig{SPort: PortRange{}, DPort: PortRange{}}
+ tcpHdr := TCPConfig{SPort: AddrRange{}, DPort: AddrRange{}}
for k, v := range in {
switch strings.ToLower(k) {
case "sport":
@@ -451,12 +444,11 @@ func parseTCPHdr(in map[string]interface{}) (TCPConfig, error) {
}
tcpHdr.Flags = flags
default:
- data, dataType, err := parseData(map[string]interface{}{k: v})
+ data, err := parseData(map[string]interface{}{k: v})
if err != nil {
return TCPConfig{}, fmt.Errorf("parseData for tcp returned: %v", err)
}
- tcpHdr.Data = data
- tcpHdr.DType = dataType
+ tcpHdr.Bytes = data
break
}
}
@@ -464,7 +456,7 @@ func parseTCPHdr(in map[string]interface{}) (TCPConfig, error) {
}
func parseUDPHdr(in map[string]interface{}) (UDPConfig, error) {
- udpHdr := UDPConfig{SPort: PortRange{}, DPort: PortRange{}}
+ udpHdr := UDPConfig{SPort: AddrRange{}, DPort: AddrRange{}}
for k, v := range in {
switch strings.ToLower(k) {
case "sport":
@@ -480,12 +472,11 @@ func parseUDPHdr(in map[string]interface{}) (UDPConfig, error) {
}
udpHdr.DPort = dport
default:
- data, dataType, err := parseData(map[string]interface{}{k: v})
+ data, err := parseData(map[string]interface{}{k: v})
if err != nil {
return UDPConfig{}, fmt.Errorf("parseData for udp returned: %v", err)
}
- udpHdr.Data = data
- udpHdr.DType = dataType
+ udpHdr.Bytes = data
break
}
}
@@ -493,7 +484,7 @@ func parseUDPHdr(in map[string]interface{}) (UDPConfig, error) {
}
func parseICMPHdr(in map[string]interface{}) (ICMPConfig, error) {
- icmpHdr := ICMPConfig{Data: unsafe.Pointer(&Raw{Data: ""})}
+ icmpHdr := ICMPConfig{Bytes: RawBytes{Data: ""}}
for k, v := range in {
switch strings.ToLower(k) {
case "type":
@@ -509,38 +500,37 @@ func parseICMPHdr(in map[string]interface{}) (ICMPConfig, error) {
}
icmpHdr.Seq = seq
default:
- data, dataType, err := parseData(map[string]interface{}{k: v})
+ data, err := parseData(map[string]interface{}{k: v})
if err != nil {
return ICMPConfig{}, fmt.Errorf("parseData for icmp returned: %v", err)
}
- icmpHdr.Data = data
- icmpHdr.DType = dataType
+ icmpHdr.Bytes = data
break
}
}
return icmpHdr, nil
}
-func parseTCPFlags(in []interface{}) (ret common.TCPFlags, err error) {
+func parseTCPFlags(in []interface{}) (ret types.TCPFlags, err error) {
ret = 0
for _, flag := range in {
switch strings.ToLower(flag.(string)) {
case "fin":
- ret ^= common.TCPFlagFin
+ ret ^= types.TCPFlagFin
case "syn":
- ret ^= common.TCPFlagSyn
+ ret ^= types.TCPFlagSyn
case "rst":
- ret ^= common.TCPFlagRst
+ ret ^= types.TCPFlagRst
case "psh":
- ret ^= common.TCPFlagPsh
+ ret ^= types.TCPFlagPsh
case "ack":
- ret ^= common.TCPFlagAck
+ ret ^= types.TCPFlagAck
case "urg":
- ret ^= common.TCPFlagUrg
+ ret ^= types.TCPFlagUrg
case "ece":
- ret ^= common.TCPFlagEce
+ ret ^= types.TCPFlagEce
case "cwr":
- ret ^= common.TCPFlagCwr
+ ret ^= types.TCPFlagCwr
default:
return 0, fmt.Errorf("unknown flag value: %s", flag.(string))
}
@@ -551,24 +541,24 @@ func parseTCPFlags(in []interface{}) (ret common.TCPFlags, err error) {
func parseSeq(in string) (Sequence, error) {
switch strings.ToLower(in) {
case "rand", "random":
- return Sequence{Type: RANDOM, Next: rand.Uint32()}, nil
+ return Sequence{Type: RANDOM, Current: rand.Uint32()}, nil
case "incr", "increasing":
- return Sequence{Type: INCREASING, Next: 0}, nil
+ return Sequence{Type: INCREASING, Current: 0}, nil
}
return Sequence{}, fmt.Errorf("unknown key for tcp sequence: %s", in)
}
-func parseRaw(in map[string]interface{}) (Raw, error) {
+func parseRaw(in map[string]interface{}) (string, error) {
for k, v := range in {
switch strings.ToLower(k) {
case "data":
- return Raw{Data: v.(string)}, nil
+ return v.(string), nil
default:
- return Raw{}, fmt.Errorf("unknown key in 'raw' block: %s", k)
+ return "", fmt.Errorf("unknown key in 'raw' block: %s", k)
}
}
- return Raw{}, fmt.Errorf("no key 'data' found inside 'raw' block")
+ return "", fmt.Errorf("no key 'data' found inside 'raw' block")
}
func parseRandBytes(in map[string]interface{}) (RandBytes, error) {
@@ -595,18 +585,22 @@ func parseRandBytes(in map[string]interface{}) (RandBytes, error) {
func parsePdist(in []interface{}) ([]PDistEntry, error) {
pdist := []PDistEntry{}
+ var totalProb float64
for _, v := range in {
pdistElem, err := parsePdistEntry(v.(map[string]interface{}))
if err != nil {
return []PDistEntry{}, fmt.Errorf("parsing pdistentry returned: %v", err)
}
+ totalProb += pdistElem.Probability
pdist = append(pdist, pdistElem)
}
+ if totalProb != 1 {
+ return []PDistEntry{{}}, fmt.Errorf("Sum of probabilities of pdist elements is not equal to 1")
+ }
return pdist, nil
}
-func parsePdistEntry(in map[string]interface{}) (PDistEntry, error) {
- pdistElem := PDistEntry{}
+func parsePdistEntry(in map[string]interface{}) (pdistElem PDistEntry, err error) {
for k, v := range in {
switch strings.ToLower(k) {
case "probability":
@@ -615,18 +609,16 @@ func parsePdistEntry(in map[string]interface{}) (PDistEntry, error) {
return PDistEntry{}, fmt.Errorf("invalid probability value: %f", pdistElem.Probability)
}
case "raw":
- data, err := parseRaw(v.(map[string]interface{}))
+ pdistElem.Data, err = parseRaw(v.(map[string]interface{}))
if err != nil {
return PDistEntry{}, fmt.Errorf("parsing pdist entry: parseRaw returned %v", err)
}
- pdistElem.Data = unsafe.Pointer(&data)
pdistElem.DType = RAWDATA
case "randbytes":
- randBytes, err := parseRandBytes(v.(map[string]interface{}))
+ pdistElem.Rand, err = parseRandBytes(v.(map[string]interface{}))
if err != nil {
return PDistEntry{}, fmt.Errorf("parsing pdist entry: parseRandBytes returned %v", err)
}
- pdistElem.Data = unsafe.Pointer(&randBytes)
pdistElem.DType = RANDDATA
default:
return PDistEntry{}, fmt.Errorf("unknown key %s", k)
@@ -635,7 +627,7 @@ func parsePdistEntry(in map[string]interface{}) (PDistEntry, error) {
return pdistElem, nil
}
-func parseMacAddr(value interface{}) (AddrRange, error) {
+func parseMacAddr(value interface{}) (ret AddrRange, err error) {
switch v2 := value.(type) {
case map[string]interface{}:
for k, v := range v2 {
@@ -646,51 +638,43 @@ func parseMacAddr(value interface{}) (AddrRange, error) {
return AddrRange{}, fmt.Errorf("parseAddrRange returned: %v", err)
}
return saddrRange, nil
-
default:
return AddrRange{}, fmt.Errorf("unknown key in parse mac addr: %s", k)
}
}
case string:
- saddr, err := net.ParseMAC(v2)
+ ret.Current, err = parseRawMACAddr(v2)
if err != nil {
return AddrRange{}, fmt.Errorf("parsing mac saddr returned: %v", err)
}
- ret := AddrRange{}
- ret.Min = make([]byte, len(saddr))
- copy(ret.Min, saddr)
- ret.Max = make([]byte, len(saddr))
- copy(ret.Max, saddr)
- ret.Current = make([]byte, len(saddr))
- copy(ret.Current, saddr)
return ret, nil
}
return AddrRange{}, fmt.Errorf("unknown type")
}
-func parseRawIPAddr(rawAddr string) ([]uint8, error) {
+func parseRawIPv4Addr(rawAddr string) (uint64, error) {
addr := net.ParseIP(rawAddr)
if addr == nil {
- return nil, fmt.Errorf("parsing ip addr could not parse address for %s", rawAddr)
+ return 0, fmt.Errorf("parsing ip addr could not parse address for %s", rawAddr)
}
- return addr, nil
+ return uint64(addr[12])<<24 | uint64(addr[13])<<16 | uint64(addr[14])<<8 | uint64(addr[15]), nil
}
-func parseRawMACAddr(rawAddr string) ([]uint8, error) {
+func parseRawMACAddr(rawAddr string) (uint64, error) {
addr, err := net.ParseMAC(rawAddr)
if err != nil {
- return nil, fmt.Errorf("parsing mac addr returned: %v for %s", err, rawAddr)
+ return 0, fmt.Errorf("parsing mac addr returned: %v for %s", err, rawAddr)
}
- return addr, nil
+ return uint64(addr[0])<<40 | uint64(addr[1])<<32 | uint64(addr[2])<<24 | uint64(addr[3])<<16 | uint64(addr[4])<<8 | uint64(addr[5]), nil
}
-func parseIPAddr(value interface{}) (AddrRange, error) {
+func parseIPv4Addr(value interface{}) (ret AddrRange, err error) {
switch v2 := value.(type) {
case map[string]interface{}:
for k, v := range v2 {
switch strings.ToLower(k) {
case "range":
- addrRange, err := parseAddrRange(v.(map[string]interface{}), parseRawIPAddr)
+ addrRange, err := parseAddrRange(v.(map[string]interface{}), parseRawIPv4Addr)
if err != nil {
return AddrRange{}, fmt.Errorf("parseAddrRange returned: %v", err)
}
@@ -700,56 +684,42 @@ func parseIPAddr(value interface{}) (AddrRange, error) {
}
}
case string:
- saddr, err := parseRawIPAddr(v2)
+ ret.Current, err = parseRawIPv4Addr(v2)
if err != nil {
return AddrRange{}, fmt.Errorf("parsing ip addr returned: %v", err)
}
- ret := AddrRange{}
- ret.Min = make([]byte, len(saddr))
- copy(ret.Min, saddr)
- ret.Max = make([]byte, len(saddr))
- copy(ret.Max, saddr)
- ret.Current = make([]byte, len(saddr))
- copy(ret.Current, saddr)
return ret, nil
}
return AddrRange{}, fmt.Errorf("unknown type")
}
-type fn func(string) ([]uint8, error)
+type fn func(string) (uint64, error)
-func parseAddrRange(in map[string]interface{}, parseFunc fn) (AddrRange, error) {
- addr := AddrRange{}
- wasMin, wasMax, wasStart, wasIncr := false, false, false, false
+func parseAddrRange(in map[string]interface{}, parseFunc fn) (addr AddrRange, err error) {
+ wasMin, wasMax, wasStart, wasInc := false, false, false, false
for k, v := range in {
switch strings.ToLower(k) {
case "min":
- min, err := parseFunc(v.(string))
+ addr.Min, err = parseFunc(v.(string))
if err != nil {
return AddrRange{}, fmt.Errorf("parsing min returned: %v", err)
}
- addr.Min = make([]byte, len(min))
- copy(addr.Min, min)
wasMin = true
case "max":
- max, err := parseFunc(v.(string))
+ addr.Max, err = parseFunc(v.(string))
if err != nil {
return AddrRange{}, fmt.Errorf("parsing max returned: %v", err)
}
- addr.Max = make([]byte, len(max))
- copy(addr.Max, max)
wasMax = true
case "start":
- start, err := parseFunc(v.(string))
+ addr.Current, err = parseFunc(v.(string))
if err != nil {
return AddrRange{}, fmt.Errorf("parsing start returned: %v", err)
}
- addr.Current = make([]byte, len(start))
- copy(addr.Current, start)
wasStart = true
- case "incr":
- addr.Incr = big.NewInt((int64)(v.(float64))).Bytes()
- wasIncr = true
+ case "inc":
+ addr.Inc = (uint64)(v.(float64))
+ wasInc = true
default:
return AddrRange{}, fmt.Errorf("unknown key %s", k)
}
@@ -757,24 +727,23 @@ func parseAddrRange(in map[string]interface{}, parseFunc fn) (AddrRange, error)
if !wasMax || !wasMin {
return AddrRange{}, fmt.Errorf("Min and max values should be given for range")
}
- if bytes.Compare(addr.Max, addr.Min) < 0 {
+ if addr.Max < addr.Min {
return AddrRange{}, fmt.Errorf("Min value should be less than Max")
}
if !wasStart {
- addr.Current = make([]byte, len(addr.Min))
- copy(addr.Current, addr.Min)
+ addr.Current = addr.Min
}
- if bytes.Compare(addr.Current, addr.Min) < 0 || bytes.Compare(addr.Current, addr.Max) > 0 {
+ if addr.Current < addr.Min || addr.Current > addr.Max {
return AddrRange{}, fmt.Errorf(fmt.Sprintf("Start value should be between min and max: start=%v, min=%v, max=%v", addr.Current, addr.Min, addr.Max))
}
- if !wasIncr {
- addr.Incr = []byte{1}
+ if !wasInc {
+ addr.Inc = 1
}
return addr, nil
}
-func parsePort(in interface{}) (PortRange, error) {
+func parsePort(in interface{}) (AddrRange, error) {
switch v2 := in.(type) {
case map[string]interface{}:
for k, v := range v2 {
@@ -782,70 +751,70 @@ func parsePort(in interface{}) (PortRange, error) {
case "range":
portRng, err := parsePortRange(v.(map[string]interface{}))
if err != nil {
- return PortRange{}, fmt.Errorf("parseAddrRange returned: %v", err)
+ return AddrRange{}, fmt.Errorf("parseAddrRange returned: %v", err)
}
return portRng, nil
default:
- return PortRange{}, fmt.Errorf("unknown key in port: %s", k)
+ return AddrRange{}, fmt.Errorf("unknown key in port: %s", k)
}
}
case float64:
if in.(float64) < 0 {
- return PortRange{}, fmt.Errorf("Port should be positive")
+ return AddrRange{}, fmt.Errorf("Port should be positive")
}
- port := (uint16)(in.(float64))
- return PortRange{Min: port, Max: port, Current: port, Incr: 0}, nil
+ port := (uint64)(in.(float64))
+ return AddrRange{Min: port, Max: port, Current: port, Inc: 0}, nil
}
- return PortRange{}, fmt.Errorf("unknown type")
+ return AddrRange{}, fmt.Errorf("unknown type")
}
-func parsePortRange(in map[string]interface{}) (PortRange, error) {
- portRng := PortRange{Incr: 0}
- wasMin, wasMax, wasStart, wasIncr := false, false, false, false
+func parsePortRange(in map[string]interface{}) (AddrRange, error) {
+ portRng := AddrRange{Inc: 0}
+ wasMin, wasMax, wasStart, wasInc := false, false, false, false
for k, v := range in {
switch strings.ToLower(k) {
case "min":
if v.(float64) < 0 {
- return PortRange{}, fmt.Errorf("Min should be positive")
+ return AddrRange{}, fmt.Errorf("Min should be positive")
}
- portRng.Min = (uint16)(v.(float64))
+ portRng.Min = (uint64)(v.(float64))
wasMin = true
case "max":
if v.(float64) < 0 {
- return PortRange{}, fmt.Errorf("Max should be positive")
+ return AddrRange{}, fmt.Errorf("Max should be positive")
}
- portRng.Max = (uint16)(v.(float64))
+ portRng.Max = (uint64)(v.(float64))
wasMax = true
case "start":
if v.(float64) < 0 {
- return PortRange{}, fmt.Errorf("Start should be positive")
+ return AddrRange{}, fmt.Errorf("Start should be positive")
}
- portRng.Current = (uint16)(v.(float64))
+ portRng.Current = (uint64)(v.(float64))
wasStart = true
- case "incr":
+ case "inc":
if v.(float64) < 0 {
- return PortRange{}, fmt.Errorf("Incr should be positive")
+ return AddrRange{}, fmt.Errorf("Inc should be positive")
}
- portRng.Incr = (uint16)(v.(float64))
- wasIncr = true
+ portRng.Inc = (uint64)(v.(float64))
+ wasInc = true
default:
- return PortRange{}, fmt.Errorf("unknown key %s", k)
+ return AddrRange{}, fmt.Errorf("unknown key %s", k)
}
}
if !wasMax || !wasMin {
- return PortRange{}, fmt.Errorf("Min and max values should be given for range")
+ return AddrRange{}, fmt.Errorf("Min and max values should be given for range")
}
if portRng.Max < portRng.Min {
- return PortRange{}, fmt.Errorf("Min value should be <= Max value")
+ return AddrRange{}, fmt.Errorf("Min value should be <= Max value")
}
if !wasStart {
portRng.Current = portRng.Min
}
if portRng.Current < portRng.Min || portRng.Current > portRng.Max {
- return PortRange{}, fmt.Errorf("Start should be in range of min and max")
+ return AddrRange{}, fmt.Errorf("Start should be in range of min and max")
}
- if !wasIncr {
- portRng.Incr = 1
+ if !wasInc {
+ portRng.Inc = 1
}
return portRng, nil
}
diff --git a/examples/nffPktgen/generator/utility.go b/examples/nffPktgen/generator/utility.go
new file mode 100644
index 00000000..ea1071d1
--- /dev/null
+++ b/examples/nffPktgen/generator/utility.go
@@ -0,0 +1,156 @@
+// Copyright 2018 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package generator
+
+import (
+ "fmt"
+ "math/rand"
+ "os"
+ "sync/atomic"
+
+ "github.com/intel-go/nff-go/flow"
+ "github.com/intel-go/nff-go/packet"
+)
+
+var gen generator
+
+type generator struct {
+ count uint64
+}
+
+// GetGenerator returns generator struct pointer
+// generator is single and created only once
+func GetGenerator() *generator {
+ return &gen
+}
+
+// GetGeneratedNumber returns a number of packets generated
+func (g *generator) GetGeneratedNumber() uint64 {
+ return atomic.LoadUint64(&(g.count))
+}
+
+// ReadConfig function reads and parses config file.
+func ReadConfig(fileName string) ([]MixConfig, error) {
+ f, err := os.Open(fileName)
+ if err != nil {
+ return nil, fmt.Errorf("opening file failed with: %v ", err)
+ }
+ cfg, err := ParseConfig(f)
+ if err != nil {
+ return nil, fmt.Errorf("parsing config failed with: %v", err)
+ }
+ return cfg, nil
+}
+
+func getGenerator(configuration PacketConfig) (func(*packet.Packet, *PacketConfig, *rand.Rand), error) {
+ switch configuration.DType {
+ case ETHERHDR:
+ l2 := configuration.Ether
+ switch l2.DType {
+ case IPv4HDR:
+ l3 := l2.IPv4
+ switch l3.DType {
+ case TCPHDR:
+ return generateTCPIPv4, nil
+ case UDPHDR:
+ return generateUDPIPv4, nil
+ case ICMPHDR:
+ return generateICMPIPv4, nil
+ case DATA:
+ return generateIPv4, nil
+ default:
+ return nil, fmt.Errorf("unknown packet l4 configuration")
+ }
+ case IPv6HDR:
+ l3 := l2.IPv6
+ switch l3.DType {
+ case TCPHDR:
+ return generateTCPIPv6, nil
+ case UDPHDR:
+ return generateUDPIPv6, nil
+ case ICMPHDR:
+ return generateICMPIPv6, nil
+ case DATA:
+ return generateIPv6, nil
+ default:
+ return nil, fmt.Errorf("unknown packet l4 configuration")
+ }
+ case ARPHDR:
+ return generateARP, nil
+ case DATA:
+ return generateEther, nil
+ default:
+ return nil, fmt.Errorf("unknown packet l3 configuration")
+ }
+ default:
+ return nil, fmt.Errorf("unknown packet l2 configuration")
+ }
+}
+
+// one unit for each mix
+type generatorTableUnit struct {
+ have, need uint32
+ generatorFunc func(*packet.Packet, *PacketConfig, *rand.Rand)
+ config PacketConfig
+}
+
+func (gtu *generatorTableUnit) String() string {
+ return fmt.Sprintf("need: %d, config: %v\n", gtu.need, gtu.config)
+}
+
+type genParameters struct {
+ table []generatorTableUnit
+ next uint32
+ length uint32
+ rnd *rand.Rand
+}
+
+func (gp genParameters) Copy() interface{} {
+ ret := new(genParameters)
+ ret.table = make([]generatorTableUnit, len(gp.table))
+ copy(ret.table, gp.table)
+ ret.length = gp.length
+ ret.rnd = rand.New(rand.NewSource(13))
+ return ret
+}
+
+func (gp genParameters) Delete() {
+}
+
+// GetContext gets generator context according to config
+func GetContext(mixConfig []MixConfig) (*genParameters, error) {
+ var t []generatorTableUnit
+ for _, packetConfig := range mixConfig {
+ genFunc, err := getGenerator(packetConfig.Config)
+ if err != nil {
+ return nil, err
+ }
+ tu := generatorTableUnit{have: 0, need: packetConfig.Quantity, generatorFunc: genFunc, config: packetConfig.Config}
+ t = append(t, tu)
+ }
+ ret := new(genParameters)
+ ret.table = t
+ ret.length = uint32(len(t))
+ ret.rnd = rand.New(rand.NewSource(13))
+ return ret, nil
+}
+
+// Generate is a main generatior func
+func Generate(pkt *packet.Packet, context flow.UserContext) {
+ genP := context.(*genParameters)
+ if genP.length > 1 {
+ if genP.table[genP.next].have == genP.table[genP.next].need {
+ genP.table[genP.next].have = 0
+ if genP.next+1 < genP.length {
+ genP.next++
+ } else {
+ genP.next = 0
+ }
+ }
+ }
+ genP.table[genP.next].generatorFunc(pkt, &genP.table[genP.next].config, genP.rnd)
+ atomic.AddUint64(&(gen.count), 1)
+ genP.table[genP.next].have++
+}
diff --git a/examples/nffPktgen/perfTest/.gitignore b/examples/nffPktgen/perfTest/.gitignore
deleted file mode 100644
index fe034ff6..00000000
--- a/examples/nffPktgen/perfTest/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-perfTest
diff --git a/examples/nffPktgen/sendGetBack/.gitignore b/examples/nffPktgen/sendGetBack/.gitignore
deleted file mode 100644
index 820c9c8e..00000000
--- a/examples/nffPktgen/sendGetBack/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-sendGetBack
diff --git a/examples/nffPktgen/testing/.gitignore b/examples/nffPktgen/testing/.gitignore
new file mode 100644
index 00000000..eb624839
--- /dev/null
+++ b/examples/nffPktgen/testing/.gitignore
@@ -0,0 +1,3 @@
+sendGetBack
+perfTest
+dump
diff --git a/examples/nffPktgen/sendGetBack/Dockerfile b/examples/nffPktgen/testing/Dockerfile
similarity index 93%
rename from examples/nffPktgen/sendGetBack/Dockerfile
rename to examples/nffPktgen/testing/Dockerfile
index 83a9e9b9..fe79ce59 100644
--- a/examples/nffPktgen/sendGetBack/Dockerfile
+++ b/examples/nffPktgen/testing/Dockerfile
@@ -9,3 +9,5 @@ LABEL RUN docker run -it --privileged -v /sys/bus/pci/drivers:/sys/bus/pci/drive
WORKDIR /workdir
COPY sendGetBack .
+COPY perfTesting .
+COPY dump .
diff --git a/examples/nffPktgen/perfTest/Makefile b/examples/nffPktgen/testing/Makefile
similarity index 84%
rename from examples/nffPktgen/perfTest/Makefile
rename to examples/nffPktgen/testing/Makefile
index 769c07ee..8e31b4fe 100644
--- a/examples/nffPktgen/perfTest/Makefile
+++ b/examples/nffPktgen/testing/Makefile
@@ -4,6 +4,6 @@
PATH_TO_MK = ../../../mk
IMAGENAME = nff-pktgen
-EXECUTABLES = perfTest
+EXECUTABLES = sendGetBack perfTest dump
include $(PATH_TO_MK)/leaf.mk
diff --git a/examples/nffPktgen/sendGetBack/README.md b/examples/nffPktgen/testing/README.md
similarity index 100%
rename from examples/nffPktgen/sendGetBack/README.md
rename to examples/nffPktgen/testing/README.md
diff --git a/examples/nffPktgen/testing/arp.json b/examples/nffPktgen/testing/arp.json
index 84db0630..0769f580 100644
--- a/examples/nffPktgen/testing/arp.json
+++ b/examples/nffPktgen/testing/arp.json
@@ -4,7 +4,7 @@
"opcode": 1,
"gratuitous" : true,
"sha": "99:25:96:FF:FE:12",
- "spa": "1.1.1.1"
+ "spa": "1.1.1.2"
}
}
}
diff --git a/examples/nffPktgen/testing/arpVlan.json b/examples/nffPktgen/testing/arpVlan.json
index 606d94c6..94eb5fba 100644
--- a/examples/nffPktgen/testing/arpVlan.json
+++ b/examples/nffPktgen/testing/arpVlan.json
@@ -1,12 +1,11 @@
{
"ether": {
"vlan-tci": 200,
- "daddr": "00:25:96:FF:FE:12",
"arp": {
"opcode": 1,
"gratuitous" : true,
"sha": "99:25:96:FF:FE:12",
- "spa": "1.1.1.1"
+ "spa": "1.1.1.2"
}
}
}
diff --git a/examples/nffPktgen/testing/config.json b/examples/nffPktgen/testing/config.json
index c0f03244..36f388c0 100644
--- a/examples/nffPktgen/testing/config.json
+++ b/examples/nffPktgen/testing/config.json
@@ -5,12 +5,11 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 3
+ "inc": 3
}
},
"daddr": "00:FF:96:FF:FE:12",
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": {
"range": {
"min": "1.1.127.1",
@@ -40,4 +39,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/dump.go b/examples/nffPktgen/testing/dump.go
new file mode 100644
index 00000000..43236f44
--- /dev/null
+++ b/examples/nffPktgen/testing/dump.go
@@ -0,0 +1,45 @@
+// Copyright 2018 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "github.com/intel-go/nff-go/examples/nffPktgen/generator"
+ "github.com/intel-go/nff-go/flow"
+ "github.com/intel-go/nff-go/packet"
+ "os"
+)
+
+func main() {
+ name := flag.String("m", "", "filename")
+ flag.Parse()
+ // Init NFF-GO system at 16 available cores
+ config := flow.Config{
+ CPUList: "0-43",
+ DisableScheduler: true,
+ }
+ flow.CheckFatal(flow.SystemInit(&config))
+
+ configuration, err := generator.ReadConfig(*name)
+ flow.CheckFatal(err)
+ context, err1 := generator.GetContext(configuration)
+ flow.CheckFatal(err1)
+
+ outFlow, _, _ := flow.SetFastGenerator(generator.Generate, 100, context)
+ flow.SetHandler(outFlow, handleRecv, nil)
+ flow.SetStopper(outFlow)
+ flow.CheckFatal(flow.SystemStart())
+}
+
+var got int
+
+func handleRecv(currentPacket *packet.Packet, context flow.UserContext) {
+ got++
+ fmt.Printf("Raw bytes=%x\n", currentPacket.GetRawPacketBytes())
+ if got > 25 {
+ os.Exit(0)
+ }
+}
diff --git a/examples/nffPktgen/testing/ether.json b/examples/nffPktgen/testing/ether.json
index 3b50e306..fbce7af4 100644
--- a/examples/nffPktgen/testing/ether.json
+++ b/examples/nffPktgen/testing/ether.json
@@ -5,7 +5,7 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 10
+ "inc": 10
}
},
"daddr": "00:FF:96:FF:FE:12",
@@ -14,4 +14,4 @@
"deviation": 300
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/ip4.json b/examples/nffPktgen/testing/ip4.json
index d7de24ef..20749859 100644
--- a/examples/nffPktgen/testing/ip4.json
+++ b/examples/nffPktgen/testing/ip4.json
@@ -4,17 +4,16 @@
"range": {
"min": "00:25:96:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 10
+ "inc": 10
}
},
"daddr": "00:00:96:FF:00:00",
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": "1.1.127.1",
"daddr": {
"range": {
"min": "1.1.1.1",
- "max": "3.3.3.3"
+ "max": "1.1.3.3"
}
},
diff --git a/examples/nffPktgen/testing/ip4icmp.json b/examples/nffPktgen/testing/ip4icmp.json
index 8ee23c1c..2b80b1bd 100644
--- a/examples/nffPktgen/testing/ip4icmp.json
+++ b/examples/nffPktgen/testing/ip4icmp.json
@@ -5,12 +5,11 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 3
+ "inc": 3
}
},
"daddr": "00:FF:96:FF:FE:12",
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": "1.1.127.1",
"daddr": "1.1.127.0",
"icmp": {
@@ -19,20 +18,20 @@
"seq": "increasing",
"pdist": [
{
- "probability": 0.3,
+ "probability": 0.33,
"randbytes": {
"size": 50,
"deviation": 10
}
},
{
- "probability": 0.3,
+ "probability": 0.33,
"raw": {
"data": "sfsfsfs"
}
},
{
- "probability": 0.3,
+ "probability": 0.34,
"raw": {
"data": "0000000000000000000000000000000000"
}
@@ -41,4 +40,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/ip4tcp.json b/examples/nffPktgen/testing/ip4tcp.json
index be567d51..c18d59e2 100644
--- a/examples/nffPktgen/testing/ip4tcp.json
+++ b/examples/nffPktgen/testing/ip4tcp.json
@@ -5,12 +5,11 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 3
+ "inc": 3
}
},
"daddr": "00:FF:96:FF:FE:12",
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": "1.1.127.1",
"daddr": "1.1.127.0",
"tcp": {
@@ -18,7 +17,7 @@
"range": {
"min": 1,
"max": 8080,
- "incr": 100
+ "inc": 100
}
},
"dport": 2000,
@@ -42,4 +41,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/ip4tcpVlan.json b/examples/nffPktgen/testing/ip4tcpVlan.json
index 275bf074..3cfe42fd 100644
--- a/examples/nffPktgen/testing/ip4tcpVlan.json
+++ b/examples/nffPktgen/testing/ip4tcpVlan.json
@@ -5,13 +5,12 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 3
+ "inc": 3
}
},
"daddr": "00:FF:96:FF:FE:12",
"vlan-tci": 123,
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": "1.1.127.1",
"daddr": "1.1.127.0",
"tcp": {
@@ -19,7 +18,7 @@
"range": {
"min": 1,
"max": 8080,
- "incr": 100
+ "inc": 100
}
},
"dport": 2000,
@@ -43,4 +42,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/ip4udp.json b/examples/nffPktgen/testing/ip4udp.json
index 5f9f498a..d3c89221 100644
--- a/examples/nffPktgen/testing/ip4udp.json
+++ b/examples/nffPktgen/testing/ip4udp.json
@@ -5,12 +5,11 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 3
+ "inc": 3
}
},
"daddr": "00:FF:96:FF:FE:12",
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": "1.1.127.1",
"daddr": "1.1.127.0",
"udp": {
@@ -18,7 +17,7 @@
"range": {
"min": 1,
"max": 8080,
- "incr": 100
+ "inc": 100
}
},
"dport": 2000,
@@ -40,4 +39,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/ip4udpVlan.json b/examples/nffPktgen/testing/ip4udpVlan.json
index a6c2b607..331c1910 100644
--- a/examples/nffPktgen/testing/ip4udpVlan.json
+++ b/examples/nffPktgen/testing/ip4udpVlan.json
@@ -5,13 +5,12 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 3
+ "inc": 3
}
},
"daddr": "00:FF:96:FF:FE:12",
"vlan-tci": 123,
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": "1.1.127.1",
"daddr": "1.1.127.0",
"udp": {
@@ -19,7 +18,7 @@
"range": {
"min": 1,
"max": 8080,
- "incr": 100
+ "inc": 100
}
},
"dport": 2000,
@@ -41,4 +40,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/ip6.json b/examples/nffPktgen/testing/ip6.json
index 10ba3b18..fa286b0e 100644
--- a/examples/nffPktgen/testing/ip6.json
+++ b/examples/nffPktgen/testing/ip6.json
@@ -4,12 +4,11 @@
"range": {
"min": "00:25:96:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 10
+ "inc": 10
}
},
"daddr": "00:00:96:FF:00:00",
- "ip": {
- "version": 6,
+ "ipv6": {
"saddr": "2001:db8:a0b:12f0::",
"pdist": [
{
@@ -21,4 +20,4 @@
]
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/ip6icmp.json b/examples/nffPktgen/testing/ip6icmp.json
index 95a45e36..955541e1 100644
--- a/examples/nffPktgen/testing/ip6icmp.json
+++ b/examples/nffPktgen/testing/ip6icmp.json
@@ -5,26 +5,25 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 3
+ "inc": 3
}
},
"daddr": "00:FF:96:FF:FE:12",
- "ip": {
- "version": 6,
+ "ipv6": {
"icmp": {
"type": 10,
"code": 1,
"seq": "increasing",
"pdist": [
{
- "probability": 0.3,
+ "probability": 0.5,
"randbytes": {
"size": 50,
"deviation": 10
}
},
{
- "probability": 0.3,
+ "probability": 0.5,
"raw": {
"data": "0000000000000000000000000000000000"
}
@@ -33,4 +32,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/ip6tcp.json b/examples/nffPktgen/testing/ip6tcp.json
index 9dcef700..374c483f 100644
--- a/examples/nffPktgen/testing/ip6tcp.json
+++ b/examples/nffPktgen/testing/ip6tcp.json
@@ -5,12 +5,11 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 3
+ "inc": 3
}
},
"daddr": "00:FF:96:FF:FE:12",
- "ip": {
- "version": 6,
+ "ipv6": {
"saddr": "2001:db8:a0b:12f0::1",
"daddr": "2001:db8:a0b:12f0::1",
"tcp": {
@@ -18,7 +17,7 @@
"range": {
"min": 1,
"max": 8080,
- "incr": 100
+ "inc": 100
}
},
"dport": 2000,
@@ -33,7 +32,7 @@
}
},
{
- "probability": 0.2,
+ "probability": 0.3,
"raw": {
"data": "sfsfsfs"
}
@@ -42,4 +41,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/ip6udp.json b/examples/nffPktgen/testing/ip6udp.json
index 344a0cf5..7e615610 100644
--- a/examples/nffPktgen/testing/ip6udp.json
+++ b/examples/nffPktgen/testing/ip6udp.json
@@ -5,12 +5,11 @@
"min": "00:25:96:FF:FE:12",
"start": "00:30:00:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 3
+ "inc": 3
}
},
"daddr": "00:FF:96:FF:FE:12",
- "ip": {
- "version": 6,
+ "ipv6": {
"saddr": "2001:db8:a0b:12f0::1",
"daddr": "2001:db8:a0b:12f0::1",
"udp": {
@@ -18,7 +17,7 @@
"range": {
"min": 1,
"max": 8080,
- "incr": 100
+ "inc": 100
}
},
"dport": 2000,
@@ -29,4 +28,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/nffPktgen/testing/mix.json b/examples/nffPktgen/testing/mix.json
index 23aa7a3b..7fc0e429 100644
--- a/examples/nffPktgen/testing/mix.json
+++ b/examples/nffPktgen/testing/mix.json
@@ -5,12 +5,11 @@
"range": {
"min": "00:25:96:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 10
+ "inc": 10
}
},
"daddr": "00:00:96:FF:00:00",
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": "1.1.127.1",
"daddr": {
"range": {
@@ -37,12 +36,11 @@
"range": {
"min": "00:25:96:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 10
+ "inc": 10
}
},
"daddr": "00:00:96:FF:00:00",
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": "1.1.127.1",
"daddr": {
"range": {
@@ -55,7 +53,7 @@
"range": {
"min": 1,
"max": 8080,
- "incr": 100
+ "inc": 100
}
},
"dport": 2000,
@@ -74,12 +72,11 @@
"range": {
"min": "00:25:96:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 10
+ "inc": 10
}
},
"daddr": "00:00:96:FF:00:00",
- "ip": {
- "version": 4,
+ "ipv4": {
"saddr": "1.1.127.1",
"daddr": {
"range": {
@@ -92,7 +89,7 @@
"range": {
"min": 1,
"max": 8080,
- "incr": 100
+ "inc": 100
}
},
"dport": 2000,
diff --git a/examples/nffPktgen/perfTest/perfTest.go b/examples/nffPktgen/testing/perfTest.go
similarity index 73%
rename from examples/nffPktgen/perfTest/perfTest.go
rename to examples/nffPktgen/testing/perfTest.go
index 01e4e733..abd7d390 100644
--- a/examples/nffPktgen/perfTest/perfTest.go
+++ b/examples/nffPktgen/testing/perfTest.go
@@ -17,9 +17,9 @@ func main() {
genConfig, cores string
port uint
)
- flag.Uint64Var(&speed, "speed", 6000000, "speed of fast generator, Pkts/s")
- flag.StringVar(&genConfig, "config", "../testing/ip4.json", "specifies config for generator")
- flag.StringVar(&cores, "cores", "0-3", "specifies cores")
+ flag.Uint64Var(&speed, "speed", 120000000, "speed of fast generator, Pkts/s")
+ flag.StringVar(&genConfig, "config", "ip4.json", "specifies config for generator")
+ flag.StringVar(&cores, "cores", "0-2", "specifies cores")
flag.UintVar(&port, "port", 1, "specifies output port")
flag.Parse()
@@ -35,8 +35,7 @@ func main() {
}
context, err := generator.GetContext(configuration)
flow.CheckFatal(err)
- outFlow, err := flow.SetFastGenerator(generator.Generate, speed, context)
- flow.CheckFatal(err)
+ outFlow, _, _ := flow.SetFastGenerator(generator.Generate, speed, context)
flow.CheckFatal(flow.SetSender(outFlow, uint16(port)))
flow.CheckFatal(flow.SystemStart())
}
diff --git a/examples/nffPktgen/testing/run.sh b/examples/nffPktgen/testing/run.sh
index 38bc1bc3..ba6ce9f9 100644
--- a/examples/nffPktgen/testing/run.sh
+++ b/examples/nffPktgen/testing/run.sh
@@ -1,18 +1,18 @@
#!/bin/bash
-../sendGetBack/sendGetBack -number 100000 -outConfig "'ether.pcap': 'ether.json'"
-../sendGetBack/sendGetBack -number 10000 -outConfig "'ip4.pcap':'ip4.json'"
-../sendGetBack/sendGetBack -number 1000 -outConfig "'ip6.pcap':'ip6.json'"
-../sendGetBack/sendGetBack -number 100000 -outConfig "'ip4tcp.pcap':'ip4tcp.json'"
-../sendGetBack/sendGetBack -number 100000 -outConfig "'ip4tcpVlan.pcap':'ip4tcpVlan.json'"
-../sendGetBack/sendGetBack -number 1000000 -outConfig "'ip6tcp.pcap':'ip6tcp.json'"
-../sendGetBack/sendGetBack -number 10000 -outConfig "'ip4udp.pcap':'ip4udp.json'"
-../sendGetBack/sendGetBack -number 10000 -outConfig "'ip4udpVlan.pcap':'ip4udpVlan.json'"
-../sendGetBack/sendGetBack -number 1000 -outConfig "'ip6udp.pcap':'ip6udp.json'"
-../sendGetBack/sendGetBack -number 1000000 -outConfig "'ip4icmp.pcap':'ip4icmp.json'"
-../sendGetBack/sendGetBack -number 100000 -outConfig "'ip6icmp.pcap':'ip6icmp.json'"
-../sendGetBack/sendGetBack -number 1000 -outConfig "'arp.pcap':'arp.json'"
-../sendGetBack/sendGetBack -number 100 -outConfig "'vlanTag.pcap':'vlanTag.json'"
-../sendGetBack/sendGetBack -number 100 -outConfig "'arpVlan.pcap':'arpVlan.json'"
-../sendGetBack/sendGetBack -number 100 -outConfig "'config.pcap': 'config.json'"
-../sendGetBack/sendGetBack -number 100 -outConfig "'mix.pcap': 'mix.json'"
\ No newline at end of file
+./sendGetBack -number 100000 -outConfig "'ether.pcap': 'ether.json'"
+./sendGetBack -number 10000 -outConfig "'ip4.pcap':'ip4.json'"
+./sendGetBack -number 1000 -outConfig "'ip6.pcap':'ip6.json'"
+./sendGetBack -number 100000 -outConfig "'ip4tcp.pcap':'ip4tcp.json'"
+./sendGetBack -number 100000 -outConfig "'ip4tcpVlan.pcap':'ip4tcpVlan.json'"
+./sendGetBack -number 1000000 -outConfig "'ip6tcp.pcap':'ip6tcp.json'"
+./sendGetBack -number 10000 -outConfig "'ip4udp.pcap':'ip4udp.json'"
+./sendGetBack -number 10000 -outConfig "'ip4udpVlan.pcap':'ip4udpVlan.json'"
+./sendGetBack -number 1000 -outConfig "'ip6udp.pcap':'ip6udp.json'"
+./sendGetBack -number 1000000 -outConfig "'ip4icmp.pcap':'ip4icmp.json'"
+./sendGetBack -number 100000 -outConfig "'ip6icmp.pcap':'ip6icmp.json'"
+./sendGetBack -number 1000 -outConfig "'arp.pcap':'arp.json'"
+./sendGetBack -number 100 -outConfig "'vlanTag.pcap':'vlanTag.json'"
+./sendGetBack -number 100 -outConfig "'arpVlan.pcap':'arpVlan.json'"
+./sendGetBack -number 100 -outConfig "'config.pcap': 'config.json'"
+./sendGetBack -number 100 -outConfig "'mix.pcap': 'mix.json'"
diff --git a/examples/nffPktgen/sendGetBack/sendGetBack.go b/examples/nffPktgen/testing/sendGetBack.go
similarity index 97%
rename from examples/nffPktgen/sendGetBack/sendGetBack.go
rename to examples/nffPktgen/testing/sendGetBack.go
index 003831bd..d40b631a 100644
--- a/examples/nffPktgen/sendGetBack/sendGetBack.go
+++ b/examples/nffPktgen/testing/sendGetBack.go
@@ -121,7 +121,8 @@ func main() {
// Init NFF-GO system at 16 available cores
config := flow.Config{
- CPUList: "0-43",
+ CPUList: "0-43",
+ DisableScheduler: true,
}
flow.CheckFatal(flow.SystemInit(&config))
@@ -136,7 +137,7 @@ func main() {
}
context, err := generator.GetContext(configuration)
flow.CheckFatal(err)
- outFlow, err := flow.SetFastGenerator(generator.Generate, speed, context)
+ outFlow, _, err := flow.SetFastGenerator(generator.Generate, speed, context)
flow.CheckFatal(err)
switch t := key.(type) {
case int:
diff --git a/examples/nffPktgen/testing/vlanTag.json b/examples/nffPktgen/testing/vlanTag.json
index ea6f30e2..77b53e99 100644
--- a/examples/nffPktgen/testing/vlanTag.json
+++ b/examples/nffPktgen/testing/vlanTag.json
@@ -4,13 +4,12 @@
"range": {
"min": "00:25:96:FF:FE:12",
"max": "00:FF:96:FF:FE:12",
- "incr": 10
+ "inc": 10
}
},
"daddr": "00:00:96:FF:00:00",
"vlan-tci": 123,
- "ip": {
- "version": 6,
+ "ipv6": {
"saddr": "2001:db8:a0b:12f0::",
"pdist": [
{
@@ -22,4 +21,4 @@
]
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/pingReplay.go b/examples/pingReplay.go
index 71053972..edabdff7 100644
--- a/examples/pingReplay.go
+++ b/examples/pingReplay.go
@@ -3,6 +3,7 @@ package main
import (
"flag"
"github.com/intel-go/nff-go/flow"
+ "github.com/intel-go/nff-go/types"
)
func main() {
@@ -14,7 +15,7 @@ func main() {
inputFlow, err := flow.SetReceiver(uint16(*inport))
flow.CheckFatal(err)
- flow.CheckFatal(flow.SetIPForPort(uint16(*inport), uint32(20)<<24|uint32(20)<<16|uint32(20)<<8|uint32(20)))
+ flow.CheckFatal(flow.SetIPForPort(uint16(*inport), types.IPv4Address(20)<<24|types.IPv4Address(20)<<16|types.IPv4Address(20)<<8|types.IPv4Address(20)))
flow.CheckFatal(flow.DealARPICMP(inputFlow))
flow.CheckFatal(flow.SetStopper(inputFlow))
diff --git a/examples/tutorial/common.go b/examples/tutorial/common.go
index 00eb401f..6d5e973b 100644
--- a/examples/tutorial/common.go
+++ b/examples/tutorial/common.go
@@ -7,16 +7,16 @@ import (
"net"
"os"
- "github.com/intel-go/nff-go/common"
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
+ "github.com/intel-go/nff-go/types"
)
var config map[string][]string
-var dstMac0 [common.EtherAddrLen]uint8
-var srcMac0 [common.EtherAddrLen]uint8
-var dstMac1 [common.EtherAddrLen]uint8
-var srcMac1 [common.EtherAddrLen]uint8
+var dstMac0 [types.EtherAddrLen]uint8
+var srcMac0 [types.EtherAddrLen]uint8
+var dstMac1 [types.EtherAddrLen]uint8
+var srcMac1 [types.EtherAddrLen]uint8
var modifyPacket = []func(pkt *packet.Packet, ctx flow.UserContext){modifyPacket0, modifyPacket1}
var direct = "direct"
@@ -38,7 +38,7 @@ func readConfig(fileName string) error {
return nil
}
-func printMAC(prompt string, mac [common.EtherAddrLen]uint8) {
+func printMAC(prompt string, mac [types.EtherAddrLen]uint8) {
log.Printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", prompt, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
}
diff --git a/examples/tutorial/step10.go b/examples/tutorial/step10.go
index 0b33345e..88be669b 100644
--- a/examples/tutorial/step10.go
+++ b/examples/tutorial/step10.go
@@ -3,7 +3,7 @@ package main
import "sync/atomic"
import "time"
import "unsafe"
-import "github.com/intel-go/nff-go/common"
+import "github.com/intel-go/nff-go/types"
import "github.com/intel-go/nff-go/flow"
import "github.com/intel-go/nff-go/packet"
@@ -43,10 +43,10 @@ func myHandler(curV []*packet.Packet, mask *[vecSize]bool, ctx flow.UserContext)
for i := uint(0); i < vecSize; i++ {
if (*mask)[i] == true {
cur := curV[i]
- cur.EncapsulateHead(common.EtherLen, common.IPv4MinLen)
+ cur.EncapsulateHead(types.EtherLen, types.IPv4MinLen)
cur.ParseL3()
- cur.GetIPv4NoCheck().SrcAddr = packet.BytesToIPv4(111, 22, 3, 0)
- cur.GetIPv4NoCheck().DstAddr = packet.BytesToIPv4(3, 22, 111, 0)
+ cur.GetIPv4NoCheck().SrcAddr = types.BytesToIPv4(111, 22, 3, 0)
+ cur.GetIPv4NoCheck().DstAddr = types.BytesToIPv4(3, 22, 111, 0)
cur.GetIPv4NoCheck().VersionIhl = 0x45
cur.GetIPv4NoCheck().NextProtoID = 0x04
}
diff --git a/examples/tutorial/step11.go b/examples/tutorial/step11.go
index 71498c7c..a619e74f 100644
--- a/examples/tutorial/step11.go
+++ b/examples/tutorial/step11.go
@@ -3,7 +3,7 @@ package main
import "sync/atomic"
import "time"
import "unsafe"
-import "github.com/intel-go/nff-go/common"
+import "github.com/intel-go/nff-go/types"
import "github.com/intel-go/nff-go/flow"
import "github.com/intel-go/nff-go/packet"
@@ -43,10 +43,10 @@ func myHandler(curV []*packet.Packet, mask *[vecSize]bool, ctx flow.UserContext)
for i := uint(0); i < vecSize; i++ {
if (*mask)[i] == true {
cur := curV[i]
- cur.EncapsulateHead(common.EtherLen, common.IPv4MinLen)
+ cur.EncapsulateHead(types.EtherLen, types.IPv4MinLen)
cur.ParseL3()
- cur.GetIPv4NoCheck().SrcAddr = packet.BytesToIPv4(111, 22, 3, 0)
- cur.GetIPv4NoCheck().DstAddr = packet.BytesToIPv4(3, 22, 111, 0)
+ cur.GetIPv4NoCheck().SrcAddr = types.BytesToIPv4(111, 22, 3, 0)
+ cur.GetIPv4NoCheck().DstAddr = types.BytesToIPv4(3, 22, 111, 0)
cur.GetIPv4NoCheck().VersionIhl = 0x45
cur.GetIPv4NoCheck().NextProtoID = 0x04
}
diff --git a/examples/tutorial/step9.go b/examples/tutorial/step9.go
index be3aeb4e..4442bb4c 100644
--- a/examples/tutorial/step9.go
+++ b/examples/tutorial/step9.go
@@ -3,7 +3,7 @@ package main
import "sync/atomic"
import "time"
import "unsafe"
-import "github.com/intel-go/nff-go/common"
+import "github.com/intel-go/nff-go/types"
import "github.com/intel-go/nff-go/flow"
import "github.com/intel-go/nff-go/packet"
@@ -38,10 +38,10 @@ func mySplitter(cur *packet.Packet, ctx flow.UserContext) uint {
}
func myHandler(cur *packet.Packet, ctx flow.UserContext) {
- cur.EncapsulateHead(common.EtherLen, common.IPv4MinLen)
+ cur.EncapsulateHead(types.EtherLen, types.IPv4MinLen)
cur.ParseL3()
- cur.GetIPv4NoCheck().SrcAddr = packet.BytesToIPv4(111, 22, 3, 0)
- cur.GetIPv4NoCheck().DstAddr = packet.BytesToIPv4(3, 22, 111, 0)
+ cur.GetIPv4NoCheck().SrcAddr = types.BytesToIPv4(111, 22, 3, 0)
+ cur.GetIPv4NoCheck().DstAddr = types.BytesToIPv4(3, 22, 111, 0)
cur.GetIPv4NoCheck().VersionIhl = 0x45
cur.GetIPv4NoCheck().NextProtoID = 0x04
}
diff --git a/flow/counters.go b/flow/counters.go
new file mode 100644
index 00000000..5de64865
--- /dev/null
+++ b/flow/counters.go
@@ -0,0 +1,424 @@
+// Copyright 2019 Intel Corporation.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flow
+
+import (
+ "encoding/json"
+ "fmt"
+ "html/template"
+ "net"
+ "net/http"
+ "strings"
+
+ "github.com/intel-go/nff-go/common"
+ "github.com/intel-go/nff-go/low"
+)
+
+const (
+ rootText = `
+/rxtx for protocol statistics gathered on all send and
+receive or /rxtx/name for individual sender/receiver port.
+/json/rxtx for JSON data structure enumerating all
+ports that have statistics or /json/rxtx/name for JSON data structure with statistics
+of indivitual individual sender/receiver port.
+`
+
+ statsSummaryTemplateText = `
+Select a node to see its counters
+