From 2db2bba44f7002269951a4c97522dc90d3f98c98 Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Fri, 25 Jan 2019 14:19:29 -0600 Subject: [PATCH 01/24] Added new option NoPacketHeadChange (default - false) Application should not use EncapsulateHead and DecapsulateHead functions with passing this option to SystemInit. On the other hand receive and generate performance will be higher with this option because it will remove unnecessary initialization --- flow/flow.go | 13 +++++++-- low/low.go | 4 +-- low/low.h | 58 +++++++++++++++++++++++++--------------- low/low_test.go | 2 +- packet/packet.go | 2 ++ packet/utils_for_test.go | 2 +- 6 files changed, 54 insertions(+), 27 deletions(-) diff --git a/flow/flow.go b/flow/flow.go index ead77aa0..4b4f3ae0 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -454,9 +454,13 @@ type Config struct { MaxRecv int // Limits parallel instances. 1 for one instance, 1000 for RSS count determine instances MaxInIndex int32 - // Scheduler should clone functions even if ti can lead to reordering. + // Scheduler should clone functions even if it can lead to reordering. // This option should be switch off for all high level reassembling like TCP or HTTP RestrictedCloning bool + // If application uses EncapsulateHead or DecapsulateHead functions L2 pointers + // should be reinit every receving or generating a packet. This can be removed if + // EncapsulateHead and DecapsulateHead are not in use + NoPacketHeadChange bool } // SystemInit is initialization of system. This function should be always called before graph construction. @@ -542,13 +546,18 @@ func SystemInit(args *Config) error { maxInIndex = args.MaxInIndex } + NoPacketHeadChange := false + if args.NoPacketHeadChange == true { + NoPacketHeadChange = true + } + argc, argv := low.InitDPDKArguments(args.DPDKArgs) // We want to add new clone if input ring is approximately 80% full maxPacketsToClone := uint32(sizeMultiplier * burstSize / 5 * 4) // TODO all low level initialization here! Now everything is default. // Init eal common.LogTitle(common.Initialization, "------------***-------- Initializing DPDK --------***------------") - if err := low.InitDPDK(argc, argv, burstSize, mbufNumber, mbufCacheSize, needKNI); err != nil { + if err := low.InitDPDK(argc, argv, burstSize, mbufNumber, mbufCacheSize, needKNI, NoPacketHeadChange); err != nil { return err } // Init Ports diff --git a/low/low.go b/low/low.go index f8d04caf..9b760e96 100644 --- a/low/low.go +++ b/low/low.go @@ -537,8 +537,8 @@ func InitDPDKArguments(args []string) (C.int, **C.char) { } // InitDPDK initializes the Environment Abstraction Layer (EAL) in DPDK. -func InitDPDK(argc C.int, argv **C.char, burstSize uint, mbufNumber uint, mbufCacheSize uint, needKNI int) error { - ret := C.eal_init(argc, argv, C.uint32_t(burstSize), C.int32_t(needKNI)) +func InitDPDK(argc C.int, argv **C.char, burstSize uint, mbufNumber uint, mbufCacheSize uint, needKNI int, NoPacketHeadChange bool) error { + ret := C.eal_init(argc, argv, C.uint32_t(burstSize), C.int32_t(needKNI), C.bool(NoPacketHeadChange)) if ret < 0 { return common.WrapWithNFError(nil, "Error with EAL initialization\n", common.FailToInitDPDK) } diff --git a/low/low.h b/low/low.h index 76a69355..14c97277 100644 --- a/low/low.h +++ b/low/low.h @@ -46,8 +46,11 @@ // 24 offset is L2 offset and is always begining of packet // 32 offset is CMbuf offset and is initilized when mempool is created // 40 offset is Next field. Should be 0. Will be filled later if required -#define mbufInit(buf) \ -*(char **)((char *)(buf) + mbufStructSize + 24) = (char *)(buf) + defaultStart; \ +#define mbufInitL2(buf) \ +*(char **)((char *)(buf) + mbufStructSize + 24) = (char *)(buf) + defaultStart; +#define mbufInitCMbuf(buf) \ +*(char **)((char *)(buf) + mbufStructSize + 32) = (char *)(buf); +#define mbufInitNextChain(buf) \ *(char **)((char *)(buf) + mbufStructSize + 40) = 0; #ifdef REASSEMBLY @@ -56,19 +59,19 @@ struct rte_ip_frag_death_row death_row; \ death_row.cnt = 0; /* DPDK doesn't initialize this field. It is probably a bug. */ \ struct rte_ip_frag_death_row* pdeath_row = &death_row; -#else -#define REASSEMBLY_INIT \ - struct rte_ip_frag_tbl* tbl = NULL; \ - struct rte_ip_frag_death_row* pdeath_row = NULL; -#endif // Firstly we set "next" packet pointer (+40) to the packet from next mbuf // Secondly we know that followed mbufs don't contain L2 and L3 headers. We assume that they start with a data // so we assume that Data packet field (+16) should be equal to Ether packet field (+24) // (which we parse at this packet segment receiving #define mbufSetNext(buf) \ -*(char **)((char *)(buf) + mbufStructSize + 40) = (char *)(buf->next) + mbufStructSize; \ -*(char **)((char *)(buf->next) + mbufStructSize + 16) = *(char **)((char *)(buf->next) + mbufStructSize + 24) + *(char **)((char *)(buf) + mbufStructSize + 40) = (char *)(buf->next) + mbufStructSize; \ + *(char **)((char *)(buf->next) + mbufStructSize + 16) = *(char **)((char *)(buf->next) + mbufStructSize + 24) +#else +#define REASSEMBLY_INIT \ + struct rte_ip_frag_tbl* tbl = NULL; \ + struct rte_ip_frag_death_row* pdeath_row = NULL; +#endif long receive_received = 0, receive_pushed = 0; long send_required = 0, send_sent = 0; @@ -77,6 +80,7 @@ long stop_freed = 0; int mbufStructSize; int headroomSize; int defaultStart; +bool L2CanBeChanged; char mempoolName[9] = "mempool1\0"; __m128 zero128 = {0, 0, 0, 0}; @@ -261,15 +265,23 @@ static inline void handleUnpushed(struct rte_mbuf *bufs[BURST_SIZE], uint16_t re __attribute__((always_inline)) static inline uint16_t handleReceived(struct rte_mbuf *bufs[BURST_SIZE], uint16_t rx_pkts_number, struct rte_ip_frag_tbl* tbl, struct rte_ip_frag_death_row* death_row) { -#ifdef REASSEMBLY +#ifndef REASSEMBLY + if (L2CanBeChanged == true) { + for (uint16_t i = 0; i < rx_pkts_number; i++) { + // TODO prefetch + mbufInitL2(bufs[i]); + } + } +#else uint16_t temp_number = 0; uint64_t cur_tsc = rte_rdtsc(); -#endif for (uint16_t i = 0; i < rx_pkts_number; i++) { // Prefetch decreases speed here without reassembly and increases with reassembly. // Speed of this is highly influenced by size of mempool. It seems that due to caches. - mbufInit(bufs[i]); -#ifdef REASSEMBLY + if (L2CanBeChanged == true) { + mbufInitL2(bufs[i]); + } + mbufInitNextChain(bufs[i]); // TODO prefetch will give 8-10% performance in reassembly case. // However we need additional investigations about small (< 3) packet numbers. //rte_prefetch0(rte_pktmbuf_mtod(bufs[i + 3] /*PREFETCH_OFFSET*/, void *)); @@ -284,9 +296,7 @@ static inline uint16_t handleReceived(struct rte_mbuf *bufs[BURST_SIZE], uint16_ } bufs[temp_number] = bufs[i]; temp_number++; -#endif } -#ifdef REASSEMBLY rx_pkts_number = temp_number; rte_ip_frag_free_death_row(death_row, 0 /* PREFETCH_OFFSET */); #endif @@ -513,7 +523,7 @@ void statistics(float N) { } // Initialize the Environment Abstraction Layer (EAL) in DPDK. -int eal_init(int argc, char *argv[], uint32_t burstSize, int32_t needKNI) +int eal_init(int argc, char *argv[], uint32_t burstSize, int32_t needKNI, bool noPacketHeadChange) { int ret = rte_eal_init(argc, argv); if (ret < 0) @@ -526,14 +536,13 @@ int eal_init(int argc, char *argv[], uint32_t burstSize, int32_t needKNI) mbufStructSize = sizeof(struct rte_mbuf); headroomSize = RTE_PKTMBUF_HEADROOM; defaultStart = mbufStructSize + headroomSize; + L2CanBeChanged = !noPacketHeadChange; if (needKNI != 0) { rte_kni_init(MAX_KNI); } return 0; } -int allocateMbufs(struct rte_mempool *mempool, struct rte_mbuf **bufs, unsigned count); - struct rte_mempool * createMempool(uint32_t num_mbufs, uint32_t mbuf_cache_size) { struct rte_mempool *mbuf_pool; @@ -549,11 +558,13 @@ struct rte_mempool * createMempool(uint32_t num_mbufs, uint32_t mbuf_cache_size) // Put mbuf addresses in all packets. It is CMbuf GO field. struct rte_mbuf **temp; temp = malloc(sizeof(struct rte_mbuf *) * num_mbufs); - allocateMbufs(mbuf_pool, temp, num_mbufs); + rte_pktmbuf_alloc_bulk(mbuf_pool, temp, num_mbufs); // This initializes CMbuf field of packet structure stored in mbuf // All CMbuf pointers is set to point to starting of corresponding mbufs for (int i = 0; i < num_mbufs; i++) { - *(char**)((char*)(temp[i]) + mbufStructSize + 32) = (char*)(temp[i]); + mbufInitL2(temp[i]) + mbufInitCMbuf(temp[i]) + mbufInitNextChain(temp[i]) } for (int i = 0; i < num_mbufs; i++) { rte_pktmbuf_free(temp[i]); @@ -567,7 +578,12 @@ int allocateMbufs(struct rte_mempool *mempool, struct rte_mbuf **bufs, unsigned int ret = rte_pktmbuf_alloc_bulk(mempool, bufs, count); if (ret == 0) { for (int i = 0; i < count; i++) { - mbufInit(bufs[i]); + if (L2CanBeChanged == true) { + mbufInitL2(bufs[i]); + } +#ifdef REASSEMBLY + mbufInitNextChain(bufs[i]); +#endif } } return ret; diff --git a/low/low_test.go b/low/low_test.go index 7be01d0f..86cb7848 100644 --- a/low/low_test.go +++ b/low/low_test.go @@ -15,7 +15,7 @@ import ( func init() { argc, argv := InitDPDKArguments([]string{}) // Default: burstSize=32, mbufNumber=8191, mbufCacheSize=250 - if err := InitDPDK(argc, argv, 32, 8191, 250, 0); err != nil { + if err := InitDPDK(argc, argv, 32, 8191, 250, 0, false); err != nil { log.Fatalf("fail to initialize with error: %+v\n", err) } rand.Seed(time.Now().UTC().UnixNano()) diff --git a/packet/packet.go b/packet/packet.go index 90f4a72c..22dd7267 100644 --- a/packet/packet.go +++ b/packet/packet.go @@ -747,6 +747,7 @@ func (packet *Packet) GetPacketPayload() ([]byte, bool) { // EncapsulateHead adds bytes to packet. start - number of beginning byte, length - number of // added bytes. This function should be used to add bytes to the first half // of packet. Return false if error. +// You must not add StableL2 option to SystemInit for using this function safely. // TODO change this for scattered packet case (multiple mbufs) func (packet *Packet) EncapsulateHead(start uint, length uint) bool { if low.PrependMbuf(packet.CMbuf, length) == false { @@ -777,6 +778,7 @@ func (packet *Packet) EncapsulateTail(start uint, length uint) bool { // DecapsulateHead removes bytes from packet. start - number of beginning byte, length - number of // removed bytes. This function should be used to remove bytes from the first half // of packet. Return false if error. +// You must not add StableL2 option to SystemInit for using this function safely. // TODO change this for scattered packet case (multiple mbufs) func (packet *Packet) DecapsulateHead(start uint, length uint) bool { if low.AdjMbuf(packet.CMbuf, length) == false { diff --git a/packet/utils_for_test.go b/packet/utils_for_test.go index bb8c5e70..78c41664 100644 --- a/packet/utils_for_test.go +++ b/packet/utils_for_test.go @@ -23,7 +23,7 @@ func tInitDPDK() { if isInit != true { argc, argv := low.InitDPDKArguments([]string{}) // burstSize=32, mbufNumber=8191, mbufCacheSize=250 - if err := low.InitDPDK(argc, argv, 32, 8191, 250, 0); err != nil { + if err := low.InitDPDK(argc, argv, 32, 8191, 250, 0, false); err != nil { log.Fatal(err) } nonPerfMempool = low.CreateMempool("Test") From a4552d9b6f8eafbe3e5507cff249c0c5ae7e6644 Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Wed, 6 Feb 2019 10:44:15 -0600 Subject: [PATCH 02/24] Updated Go version --- Dockerfile | 2 +- vagrant/Vagrantfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/vagrant/Vagrantfile b/vagrant/Vagrantfile index c373d107..9b7e6c96 100644 --- a/vagrant/Vagrantfile +++ b/vagrant/Vagrantfile @@ -126,7 +126,7 @@ echo Reassigning "${syscon}" interface to system name sudo nmcli c mod "${syscon}" connection.id 'System connection' echo Unpacking Go language into /opt -(cd /opt; sudo sh -c 'curl -L -s https://dl.google.com/go/go1.11.4.linux-amd64.tar.gz | tar zx') +(cd /opt; sudo sh -c 'curl -L -s https://dl.google.com/go/go1.11.5.linux-amd64.tar.gz | tar zx') mkdir go chmod +x ~/scripts.sh . ~/scripts.sh From ee2f7225b99562d80a223e1ea2aa913a278b5843 Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Wed, 6 Feb 2019 10:44:25 -0600 Subject: [PATCH 03/24] Fixed image names to be unique Otherwise they overwrite each other --- examples/dpi/pattern/Makefile | 2 +- examples/ipsec/perf/Makefile | 2 +- examples/ipsec/stability/Makefile | 2 +- examples/nffPktgen/perfTest/Makefile | 2 +- examples/nffPktgen/sendGetBack/Makefile | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) 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/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/nffPktgen/perfTest/Makefile b/examples/nffPktgen/perfTest/Makefile index 769c07ee..9abc8d07 100644 --- a/examples/nffPktgen/perfTest/Makefile +++ b/examples/nffPktgen/perfTest/Makefile @@ -3,7 +3,7 @@ # license that can be found in the LICENSE file. PATH_TO_MK = ../../../mk -IMAGENAME = nff-pktgen +IMAGENAME = nff-pktgen-perf EXECUTABLES = perfTest include $(PATH_TO_MK)/leaf.mk diff --git a/examples/nffPktgen/sendGetBack/Makefile b/examples/nffPktgen/sendGetBack/Makefile index 48b152d5..61e8ff54 100644 --- a/examples/nffPktgen/sendGetBack/Makefile +++ b/examples/nffPktgen/sendGetBack/Makefile @@ -3,7 +3,7 @@ # license that can be found in the LICENSE file. PATH_TO_MK = ../../../mk -IMAGENAME = nff-pktgen +IMAGENAME = nff-pktgen-sendback EXECUTABLES = sendGetBack include $(PATH_TO_MK)/leaf.mk From 272a461c7d9c4a79c9ffc15043d43b70cae4634a Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Wed, 6 Feb 2019 15:00:25 -0600 Subject: [PATCH 04/24] Updated DPDK to version 19.02 Performance seems to be the same as with version 18.11 --- dpdk/dpdk | 2 +- go.sum | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) 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/go.sum b/go.sum index 1f307a5f..b30ef8f8 100644 --- a/go.sum +++ b/go.sum @@ -42,6 +42,7 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnY golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sys v0.0.0-20181004145325-8469e314837c h1:SJ7JoQNVl3mC7EWkkONgBWgCno8LcABIJwFMkWBC+EY= golang.org/x/sys v0.0.0-20181004145325-8469e314837c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952 h1:FDfvYgoVsA7TTZSbgiqjAbfPbK47CNHdWl3h/PJtii0= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/tools v0.0.0-20181002223833-cd09f19c2f7e h1:x8cnE8uLkl6ATwMpvL/N/wYBk/53BdeePq1JaYt1zuo= golang.org/x/tools v0.0.0-20181002223833-cd09f19c2f7e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 56b26dfd183d6f81cafbf5cbc6d963d28e58b029 Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Fri, 8 Feb 2019 15:09:05 -0600 Subject: [PATCH 05/24] Rebuilding nffPktgen Better performance Better scaling Better structure --- examples/nffPktgen/Makefile | 2 +- examples/nffPktgen/generator/generator.go | 454 +++++------------- examples/nffPktgen/generator/ipv6.go | 308 ++++++++++++ examples/nffPktgen/generator/parseConfig.go | 368 +++++++------- examples/nffPktgen/generator/utility.go | 156 ++++++ examples/nffPktgen/perfTest/.gitignore | 1 - examples/nffPktgen/perfTest/Dockerfile | 11 - examples/nffPktgen/sendGetBack/.gitignore | 1 - examples/nffPktgen/sendGetBack/Makefile | 9 - examples/nffPktgen/testing/.gitignore | 3 + .../{sendGetBack => testing}/Dockerfile | 2 + .../nffPktgen/{perfTest => testing}/Makefile | 4 +- .../{sendGetBack => testing}/README.md | 0 examples/nffPktgen/testing/arp.json | 2 +- examples/nffPktgen/testing/arpVlan.json | 3 +- examples/nffPktgen/testing/config.json | 7 +- examples/nffPktgen/testing/dump.go | 45 ++ examples/nffPktgen/testing/ether.json | 4 +- examples/nffPktgen/testing/ip4.json | 7 +- examples/nffPktgen/testing/ip4icmp.json | 7 +- examples/nffPktgen/testing/ip4tcp.json | 9 +- examples/nffPktgen/testing/ip4tcpVlan.json | 9 +- examples/nffPktgen/testing/ip4udp.json | 9 +- examples/nffPktgen/testing/ip4udpVlan.json | 9 +- examples/nffPktgen/testing/ip6.json | 7 +- examples/nffPktgen/testing/ip6icmp.json | 7 +- examples/nffPktgen/testing/ip6tcp.json | 9 +- examples/nffPktgen/testing/ip6udp.json | 9 +- examples/nffPktgen/testing/mix.json | 19 +- .../{perfTest => testing}/perfTest.go | 9 +- examples/nffPktgen/testing/run.sh | 32 +- .../{sendGetBack => testing}/sendGetBack.go | 3 +- examples/nffPktgen/testing/vlanTag.json | 7 +- 33 files changed, 887 insertions(+), 645 deletions(-) create mode 100644 examples/nffPktgen/generator/ipv6.go create mode 100644 examples/nffPktgen/generator/utility.go delete mode 100644 examples/nffPktgen/perfTest/.gitignore delete mode 100644 examples/nffPktgen/perfTest/Dockerfile delete mode 100644 examples/nffPktgen/sendGetBack/.gitignore delete mode 100644 examples/nffPktgen/sendGetBack/Makefile create mode 100644 examples/nffPktgen/testing/.gitignore rename examples/nffPktgen/{sendGetBack => testing}/Dockerfile (93%) rename examples/nffPktgen/{perfTest => testing}/Makefile (75%) rename examples/nffPktgen/{sendGetBack => testing}/README.md (100%) create mode 100644 examples/nffPktgen/testing/dump.go rename examples/nffPktgen/{perfTest => testing}/perfTest.go (73%) rename examples/nffPktgen/{sendGetBack => testing}/sendGetBack.go (98%) 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/generator/generator.go b/examples/nffPktgen/generator/generator.go index d416e219..e95e7bc5 100644 --- a/examples/nffPktgen/generator/generator.go +++ b/examples/nffPktgen/generator/generator.go @@ -5,114 +5,39 @@ 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" ) -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) { @@ -122,26 +47,24 @@ func copyRand(configuration unsafe.Pointer, size uint, rnd *rand.Rand, copyTo un } } -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()) + rndN := rnd.Float64() maxProb := PDistEntry{Probability: 0} - for _, item := range *data { + for _, item := range configuration.Dist { prob += item.Probability if rndN <= prob { - return getDataSizeType(item.Data, item.DType, rnd) + return getDataSizeType1(item.Data, item.Rand, item.DType, rnd) } if item.Probability > maxProb.Probability { maxProb = item @@ -153,114 +76,30 @@ func getDataSizeType(configuration unsafe.Pointer, dtype DataType, rnd *rand.Ran // 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) + return getDataSizeType1(maxProb.Data, maxProb.Rand, 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 +108,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) + l2 := &config.Ether + l3 := &l2.ARP 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: + SHA = [common.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.SwapBytesUint32(uint32(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.SwapBytesUint32(uint32(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 = [common.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.SwapBytesUint32(uint32(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 +172,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 +263,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.SwapBytesUint32(uint32(l3.SAddr.Current)) + pktIP.DstAddr = packet.SwapBytesUint32(uint32(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 diff --git a/examples/nffPktgen/generator/ipv6.go b/examples/nffPktgen/generator/ipv6.go new file mode 100644 index 00000000..abda9a93 --- /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/common" + "github.com/intel-go/nff-go/packet" +) + +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)), common.IPv6AddrLen) + copyAddr(pktIP.DstAddr[:], getNextAddr(&(l3.DAddr)), common.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..fffbc77c 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" ) 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 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.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.Data = unsafe.Pointer(&ipConf) - ethConfig.DType = IPHDR + 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,12 +500,11 @@ 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 } } @@ -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) { @@ -605,8 +595,7 @@ func parsePdist(in []interface{}) ([]PDistEntry, error) { 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 +604,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 +622,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 +633,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 +679,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 +722,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 +746,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/perfTest/Dockerfile b/examples/nffPktgen/perfTest/Dockerfile deleted file mode 100644 index 170a9213..00000000 --- a/examples/nffPktgen/perfTest/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2017 Intel Corporation. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -ARG USER_NAME -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 . 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/sendGetBack/Makefile b/examples/nffPktgen/sendGetBack/Makefile deleted file mode 100644 index 61e8ff54..00000000 --- a/examples/nffPktgen/sendGetBack/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2017 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-sendback -EXECUTABLES = sendGetBack - -include $(PATH_TO_MK)/leaf.mk 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 75% rename from examples/nffPktgen/perfTest/Makefile rename to examples/nffPktgen/testing/Makefile index 9abc8d07..8e31b4fe 100644 --- a/examples/nffPktgen/perfTest/Makefile +++ b/examples/nffPktgen/testing/Makefile @@ -3,7 +3,7 @@ # license that can be found in the LICENSE file. PATH_TO_MK = ../../../mk -IMAGENAME = nff-pktgen-perf -EXECUTABLES = perfTest +IMAGENAME = nff-pktgen +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..e1aaf9b7 --- /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..d5c836ac 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": { @@ -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..2d04507b 100644 --- a/examples/nffPktgen/testing/ip6icmp.json +++ b/examples/nffPktgen/testing/ip6icmp.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": { "icmp": { "type": 10, "code": 1, @@ -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..8441029b 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, @@ -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..317656a5 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 98% rename from examples/nffPktgen/sendGetBack/sendGetBack.go rename to examples/nffPktgen/testing/sendGetBack.go index 003831bd..73bc0bc1 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)) 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 +} From d403142758958a31a9dd84e5e660c64abe7ae2aa Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Mon, 11 Feb 2019 14:47:16 -0600 Subject: [PATCH 06/24] nffpktgen improvements --- examples/nffPktgen/generator/generator.go | 20 +++++++------------- examples/nffPktgen/generator/parseConfig.go | 5 +++++ examples/nffPktgen/testing/ip4icmp.json | 6 +++--- examples/nffPktgen/testing/ip6icmp.json | 4 ++-- examples/nffPktgen/testing/ip6tcp.json | 2 +- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/examples/nffPktgen/generator/generator.go b/examples/nffPktgen/generator/generator.go index e95e7bc5..355f52db 100644 --- a/examples/nffPktgen/generator/generator.go +++ b/examples/nffPktgen/generator/generator.go @@ -41,9 +41,13 @@ func copyRaw(configuration unsafe.Pointer, size uint, rnd *rand.Rand, copyTo uns } 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()) } } @@ -60,23 +64,13 @@ func getDataSizeType(configuration *RawBytes, rnd *rand.Rand) (uint, unsafe.Poin case PDISTDATA: prob := 0.0 rndN := rnd.Float64() - maxProb := PDistEntry{Probability: 0} for _, item := range configuration.Dist { + // Sum of all was checked to be 1 prob += item.Probability if rndN <= prob { return getDataSizeType1(item.Data, item.Rand, item.DType, rnd) } - if item.Probability > maxProb.Probability { - maxProb = item - } - } - 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 getDataSizeType1(maxProb.Data, maxProb.Rand, maxProb.DType, rnd) } panic(fmt.Sprintf("unknown data type")) } diff --git a/examples/nffPktgen/generator/parseConfig.go b/examples/nffPktgen/generator/parseConfig.go index fffbc77c..4c8ae1bf 100644 --- a/examples/nffPktgen/generator/parseConfig.go +++ b/examples/nffPktgen/generator/parseConfig.go @@ -585,13 +585,18 @@ 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 } diff --git a/examples/nffPktgen/testing/ip4icmp.json b/examples/nffPktgen/testing/ip4icmp.json index d5c836ac..2b80b1bd 100644 --- a/examples/nffPktgen/testing/ip4icmp.json +++ b/examples/nffPktgen/testing/ip4icmp.json @@ -18,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" } diff --git a/examples/nffPktgen/testing/ip6icmp.json b/examples/nffPktgen/testing/ip6icmp.json index 2d04507b..955541e1 100644 --- a/examples/nffPktgen/testing/ip6icmp.json +++ b/examples/nffPktgen/testing/ip6icmp.json @@ -16,14 +16,14 @@ "seq": "increasing", "pdist": [ { - "probability": 0.3, + "probability": 0.5, "randbytes": { "size": 50, "deviation": 10 } }, { - "probability": 0.3, + "probability": 0.5, "raw": { "data": "0000000000000000000000000000000000" } diff --git a/examples/nffPktgen/testing/ip6tcp.json b/examples/nffPktgen/testing/ip6tcp.json index 8441029b..374c483f 100644 --- a/examples/nffPktgen/testing/ip6tcp.json +++ b/examples/nffPktgen/testing/ip6tcp.json @@ -32,7 +32,7 @@ } }, { - "probability": 0.2, + "probability": 0.3, "raw": { "data": "sfsfsfs" } From 76d739d8a7b62bd302c5f772de5817ee8c924408 Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Mon, 11 Feb 2019 15:58:06 -0600 Subject: [PATCH 07/24] Smooth low speed generate --- examples/Dockerfile | 1 + examples/Makefile | 2 +- examples/generate.go | 58 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 examples/generate.go diff --git a/examples/Dockerfile b/examples/Dockerfile index dd089d3d..6916fee3 100644 --- a/examples/Dockerfile +++ b/examples/Dockerfile @@ -19,3 +19,4 @@ COPY gtpu . COPY pingReplay . COPY timer . COPY netlink . +COPY generate . diff --git a/examples/Makefile b/examples/Makefile index 78fe0fa0..bcdeced9 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -6,7 +6,7 @@ PATH_TO_MK = ../mk IMAGENAME = nff-go-examples EXECUTABLES = dump clonablePcapDumper kni copy errorHandling timer \ createPacket sendFixedPktsNumber gtpu pingReplay \ - netlink gopacketParserExample devbind + netlink gopacketParserExample devbind generate SUBDIRS = tutorial antiddos demo fileReadWrite firewall forwarding ipsec .PHONY: dpi nffPktgen diff --git a/examples/generate.go b/examples/generate.go new file mode 100644 index 00000000..d55016c9 --- /dev/null +++ b/examples/generate.go @@ -0,0 +1,58 @@ +// 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" + "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, _ := flow.SetFastGenerator(generatePacket, 3500, nil) + flow.CheckFatal(flow.SetSender(firstFlow, outputPort)) + 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) + } +} From b54fb34c78414b208d198d7e9d7afa3ea8292a22 Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Tue, 12 Feb 2019 13:19:33 -0600 Subject: [PATCH 08/24] Added possibility of receiving and sending without DPDK Added functions SetReceiverOS and SetSenderOS which use Linux devices for receiving and sending packets (raw sockets) --- common/common.go | 1 + flow/flow.go | 72 +++++++++++++++++++++++++++++++++++++ low/low.go | 13 +++++++ low/low.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+) diff --git a/common/common.go b/common/common.go index 959c4293..bde0fc25 100644 --- a/common/common.go +++ b/common/common.go @@ -155,6 +155,7 @@ const ( FailToInitDPDK FailToCreateKNI FailToReleaseKNI + BadSocket ) // NFError is error type returned by nff-go functions diff --git a/flow/flow.go b/flow/flow.go index ead77aa0..b28fe9e5 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -46,6 +46,7 @@ var createdPorts []port var portPair map[uint32](*port) var schedState *scheduler var vEach [10][burstSize]uint8 +var devices map[string]int type Timer struct { t *time.Ticker @@ -159,6 +160,18 @@ func addReceiver(portId uint16, out low.Rings, inIndexNumber int32) { schedState.addFF("receiver", nil, recvRSS, nil, par, nil, receiveRSS, inIndexNumber) } +type receiveOSParameters struct { + out low.Rings + socket int +} + +func addOSReceiver(socket int, out low.Rings) { + par := new(receiveOSParameters) + par.socket = socket + par.out = out + schedState.addFF("OS receiver", nil, recvOS, nil, par, nil, sendReceiveKNI, 0) +} + type KNIParameters struct { in low.Rings out low.Rings @@ -236,6 +249,18 @@ func addSender(port uint16, in low.Rings, inIndexNumber int32) { schedState.addFF("sender", nil, send, nil, par, nil, sendReceiveKNI, inIndexNumber) } +type sendOSParameters struct { + in low.Rings + socket int +} + +func addSenderOS(socket int, in low.Rings, inIndexNumber int32) { + par := new(sendOSParameters) + par.socket = socket + par.in = in + schedState.addFF("sender OS", nil, sendOS, nil, par, nil, sendReceiveKNI, inIndexNumber) +} + type copyParameters struct { in low.Rings out low.Rings @@ -562,6 +587,7 @@ func SystemInit(args *Config) error { } } portPair = make(map[uint32](*port)) + devices = make(map[string]int) // Init scheduler common.LogTitle(common.Initialization, "------------***------ Initializing scheduler -----***------------") StopRing := low.CreateRings(burstSize*sizeMultiplier, maxInIndex) @@ -699,6 +725,42 @@ func SetReceiver(portId uint16) (OUT *Flow, err error) { return newFlow(rings, createdPorts[portId].InIndex), nil } +// SetReceiverOS adds function receive from Linux interface to flow graph. +// Gets name of device, will return error if can't initialize socket. +// Creates RAW socket, returns new opened flow with received packets. +func SetReceiverOS(device string) (*Flow, error) { + socketID, ok := devices[device] + if !ok { + socketID = low.InitDevice(device) + if socketID == -1 { + return nil, common.WrapWithNFError(nil, "Can't initialize socket", common.BadSocket) + } + devices[device] = socketID + } + rings := low.CreateRings(burstSize*sizeMultiplier, 1) + addOSReceiver(socketID, rings) + return newFlow(rings, 1), nil +} + +// SetSenderOS adds function send from flow graph to Linux interface. +// Gets name of device, will return error if can't initialize socket. +// Creates RAW socket, sends packets, closes input flow. +func SetSenderOS(IN *Flow, device string) error { + if err := checkFlow(IN); err != nil { + return err + } + socketID, ok := devices[device] + if !ok { + socketID = low.InitDevice(device) + if socketID == -1 { + return common.WrapWithNFError(nil, "Can't initialize socket", common.BadSocket) + } + devices[device] = socketID + } + addSenderOS(socketID, finishFlow(IN), IN.inIndexNumber) + return nil +} + // SetReceiverKNI adds function receive from KNI to flow graph. // Gets KNI device from which packets will be received. // Receive queue will be added to port automatically. @@ -1260,6 +1322,11 @@ func recvRSS(parameters interface{}, inIndex []int32, flag *int32, coreID int) { low.ReceiveRSS(uint16(srp.port.PortId), inIndex, srp.out, flag, coreID, &srp.status[index]) } +func recvOS(parameters interface{}, inIndex []int32, flag *int32, coreID int) { + srp := parameters.(*receiveOSParameters) + low.ReceiveOS(srp.socket, srp.out[0], flag, coreID) +} + func processKNI(parameters interface{}, inIndex []int32, flag *int32, coreID int) { srk := parameters.(*KNIParameters) if srk.linuxCore == true { @@ -1436,6 +1503,11 @@ func send(parameters interface{}, inIndex []int32, flag *int32, coreID int) { low.Send(srp.port, srp.in, srp.anyway, flag, coreID) } +func sendOS(parameters interface{}, inIndex []int32, flag *int32, coreID int) { + srp := parameters.(*sendOSParameters) + low.SendOS(srp.socket, srp.in, flag, coreID) +} + func merge(from low.Rings, to low.Rings) { // We should change out rings in all flow functions which we added before // and change them to one "after merge" ring. diff --git a/low/low.go b/low/low.go index 078937cb..3461cddc 100644 --- a/low/low.go +++ b/low/low.go @@ -743,3 +743,16 @@ func IntArrayToBool(value *[32]uint8) *[32]bool { func CheckHWTXChecksumCapability(port uint16) bool { return bool(C.check_hwtxchecksum_capability(C.uint16_t(port))) } + +func ReceiveOS(socket int, OUT *Ring, flag *int32, coreID int) { + m := CreateMempool("receiveOS") + C.receiveOS(C.int(socket), OUT.DPDK_ring, (*C.struct_rte_mempool)(unsafe.Pointer(m)), (*C.int)(unsafe.Pointer(flag)), C.int(coreID)) +} + +func SendOS(socket int, IN Rings, flag *int32, coreID int) { + C.sendOS(C.int(socket), C.extractDPDKRings((**C.struct_nff_go_ring)(unsafe.Pointer(&(IN[0]))), C.int32_t(len(IN))), C.int32_t(len(IN)), (*C.int)(unsafe.Pointer(flag)), C.int(coreID)) +} + +func InitDevice(device string) int { + return int(C.initDevice(C.CString(device))) +} diff --git a/low/low.h b/low/low.h index 6bbf350f..78d04307 100644 --- a/low/low.h +++ b/low/low.h @@ -19,6 +19,16 @@ #include #include +#include +#include // ETH_P_ALL +#include // snprintf +#include // memset +#include // malloc +#include // htons +#include // ioctl +#include // ifreq +#include // sockaddr_ll + #define process 1 #define stopRequest 2 #define wasStopped 9 @@ -674,3 +684,86 @@ bool check_hwtxchecksum_capability(uint16_t port_id) { rte_eth_dev_info_get(port_id, &dev_info); return (dev_info.tx_offload_capa & flags) == flags; } + +int initDevice(char *name) { + int s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (s < 1) { + fprintf(stderr, "ERROR: Can't create socket for OS send/receive\n"); + return -1; + } + + struct ifreq ifr; + memset (&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", name); + if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) { + fprintf(stderr, "ERROR: Can't find device %s\n", name); + return -1; + } + + struct sockaddr_ll myaddr; + memset(&myaddr, 0, sizeof(myaddr)); + myaddr.sll_family = AF_PACKET; + myaddr.sll_protocol = htons(ETH_P_ALL); + myaddr.sll_ifindex = ifr.ifr_ifindex; + if (bind(s, (struct sockaddr*)&myaddr, sizeof(myaddr)) < 0) { + fprintf(stderr, "ERROR: Can't bind socket to %s\n", name); + return -1; + } + + ioctl(s, SIOCGIFFLAGS, &ifr); + ifr.ifr_flags |= IFF_PROMISC; + if (ioctl(s, SIOCSIFFLAGS, &ifr) != 0) { + fprintf(stderr, "ERROR: Can't set up promiscuos mode on %s\n", name); + return -1; + } + + return s; +} + +void receiveOS(int socket, struct rte_ring *out_ring, struct rte_mempool *m, volatile int *flag, int coreId) { + setAffinity(coreId); + const int recvOSBusrst = BURST_SIZE; + struct rte_mbuf *bufs[recvOSBusrst]; + REASSEMBLY_INIT + while (*flag == process) { + // Get packets from OS + allocateMbufs(m, bufs, recvOSBusrst); + //int step = 0; + for (int i = 0; i < recvOSBusrst; i++) { + int bytes_received = recv(socket, (char *)(bufs[i]) + defaultStart, ETH_FRAME_LEN, 0); + if (unlikely(bytes_received == 0)) { + //step++; + i--; + continue; + } + rte_pktmbuf_append(bufs[i], bytes_received); + } + uint16_t rx_pkts_number = handleReceived(bufs, recvOSBusrst, tbl, pdeath_row); + uint16_t pushed_pkts_number = rte_ring_enqueue_burst(out_ring, (void*)bufs, rx_pkts_number, NULL); + // Free any packets which can't be pushed to the ring. The ring is probably full. + handleUnpushed((void*)bufs, pushed_pkts_number, rx_pkts_number); + } + *flag = wasStopped; +} + +void sendOS(int socket, struct rte_ring **in_rings, int32_t inIndexNumber, volatile int *flag, int coreId) { + setAffinity(coreId); + + struct rte_mbuf *bufs[BURST_SIZE]; + uint16_t buf; + uint16_t tx_pkts_number; + while (*flag == process) { + for (int q = 0; q < inIndexNumber; q++) { + // Get packets for TX from ring + uint16_t pkts_for_tx_number = rte_ring_mc_dequeue_burst(in_rings[q], (void*)bufs, BURST_SIZE, NULL); + + for (int i = 0; i < pkts_for_tx_number; i++) { + send(socket, (char *)(bufs[i]) + defaultStart, rte_pktmbuf_pkt_len(bufs[i]), 0); + } + // Free all packets + handleUnpushed(bufs, 0, pkts_for_tx_number); + } + } + free(in_rings); + *flag = wasStopped; +} From 7cf63602020ec3d457332c5b459d180125da19d9 Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Wed, 13 Feb 2019 14:55:54 -0600 Subject: [PATCH 09/24] Example for receive/send without DPDK --- examples/.gitignore | 2 ++ examples/Dockerfile | 1 + examples/Makefile | 2 +- examples/OSforwarding.go | 24 ++++++++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 examples/OSforwarding.go 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 6916fee3..0ab249dc 100644 --- a/examples/Dockerfile +++ b/examples/Dockerfile @@ -20,3 +20,4 @@ COPY pingReplay . COPY timer . COPY netlink . COPY generate . +COPY OSforwarding . diff --git a/examples/Makefile b/examples/Makefile index bcdeced9..85da9530 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -6,7 +6,7 @@ PATH_TO_MK = ../mk IMAGENAME = nff-go-examples EXECUTABLES = dump clonablePcapDumper kni copy errorHandling timer \ createPacket sendFixedPktsNumber gtpu pingReplay \ - netlink gopacketParserExample devbind generate + netlink gopacketParserExample devbind generate OSforwarding SUBDIRS = tutorial antiddos demo fileReadWrite firewall forwarding ipsec .PHONY: dpi nffPktgen 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()) +} From 29fe868be59d56d017e8f5f53bab5f0d817a80c2 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 13 Feb 2019 21:52:00 +0000 Subject: [PATCH 10/24] Fixed ARP target HW address which should be 0xff for AWS --- packet/arp.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packet/arp.go b/packet/arp.go index 95f4cbcc..ea8a87b2 100644 --- a/packet/arp.go +++ b/packet/arp.go @@ -86,7 +86,7 @@ func InitARPRequestPacket(packet *Packet, SHA [common.EtherAddrLen]uint8, SPA, T arp.Operation = SwapBytesUint16(ARPRequest) arp.SHA = SHA arp.SPA = IPv4ToBytes(SPA) - arp.THA = [common.EtherAddrLen]uint8{} + arp.THA = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} arp.TPA = IPv4ToBytes(TPA) return true } @@ -129,7 +129,7 @@ func InitGARPAnnouncementRequestPacket(packet *Packet, SHA [common.EtherAddrLen] arp.Operation = SwapBytesUint16(ARPRequest) arp.SHA = SHA arp.SPA = IPv4ToBytes(SPA) - arp.THA = [common.EtherAddrLen]uint8{} + arp.THA = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} arp.TPA = IPv4ToBytes(SPA) return true } @@ -151,7 +151,7 @@ func InitGARPAnnouncementReplyPacket(packet *Packet, SHA [common.EtherAddrLen]ui arp.Operation = SwapBytesUint16(ARPReply) arp.SHA = SHA arp.SPA = IPv4ToBytes(SPA) - arp.THA = [common.EtherAddrLen]uint8{} + arp.THA = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} arp.TPA = IPv4ToBytes(SPA) return true } From cd1d4fc556ab1dbd8421367fdc79455855ee932f Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Fri, 15 Feb 2019 09:17:51 -0600 Subject: [PATCH 11/24] Fixed failing tests after PR #556 --- packet/arp_test.go | 8 ++++---- packet/vlan_test.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packet/arp_test.go b/packet/arp_test.go index 06172848..0936e9b3 100644 --- a/packet/arp_test.go +++ b/packet/arp_test.go @@ -20,10 +20,10 @@ func init() { // These strings were created with gopacket library. var ( - gtLineARPRequest = "ffffffffffff00070daff4540806000108000604000100070daff45418a6ac0100000000000018a6ad9f" + gtLineARPRequest = "ffffffffffff00070daff4540806000108000604000100070daff45418a6ac01ffffffffffff18a6ad9f" gtLineARPReply = "c40132580000c402326b000008060001080006040002c402326b00000a000002c401325800000a000001" - gtLineGratARPRequest = "ffffffffffff02020202020208060001080006040001020202020202c0a80101000000000000c0a80101" - gtLineGratARPReply = "ffffffffffff00000c07ac010806000108000604000200000c07ac010a0000060000000000000a000006" + gtLineGratARPRequest = "ffffffffffff02020202020208060001080006040001020202020202c0a80101ffffffffffffc0a80101" + gtLineGratARPReply = "ffffffffffff00000c07ac010806000108000604000200000c07ac010a000006ffffffffffff0a000006" gtLineEmptyARP = "000000000000000000000000080600000000000000000000000000000000000000000000000000000000" ) @@ -37,7 +37,7 @@ func TestInitARPCommonDataPacket(t *testing.T) { pktARP := pkt.GetARP() pktARP.Operation = SwapBytesUint16(1) pktARP.SHA = [6]uint8{0x00, 0x07, 0x0d, 0xaf, 0xf4, 0x54} - pktARP.THA = [6]uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + pktARP.THA = [6]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} copy(pktARP.SPA[:], net.ParseIP("24.166.172.1").To4()[:]) copy(pktARP.TPA[:], net.ParseIP("24.166.173.159").To4()[:]) diff --git a/packet/vlan_test.go b/packet/vlan_test.go index a553da08..d1244d28 100644 --- a/packet/vlan_test.go +++ b/packet/vlan_test.go @@ -74,7 +74,7 @@ var ( Operation: SwapBytesUint16(ARPRequest), SHA: MacHeaderVLAN.SAddr, SPA: IPv4ToBytes(IPv4HeaderVLAN.SrcAddr), - THA: [EtherAddrLen]uint8{}, + THA: [EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, TPA: IPv4ToBytes(IPv4HeaderVLAN.DstAddr), } ) From c905b9a87576443a371cdb6e2c8880ea845976c7 Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Fri, 14 Dec 2018 16:02:48 -0800 Subject: [PATCH 12/24] Added special types for IPv4, IPv6 and MAC addresses --- common/common.go | 81 +++++++++++++++++++ examples/antiddos/generatorForAntiDDoS.go | 15 ++-- examples/gtpu.go | 10 +-- examples/ipsec/ipsec_kernel.go | 8 +- examples/ipsec/stability/stability.go | 23 +++--- examples/netlink.go | 16 ++-- examples/nffPktgen/generator/generator.go | 10 +-- examples/pingReplay.go | 3 +- examples/tutorial/step10.go | 4 +- examples/tutorial/step11.go | 4 +- examples/tutorial/step9.go | 4 +- flow/flow.go | 10 +-- flow/predefined.go | 4 +- low/low.go | 4 +- packet/acl.go | 24 +++--- packet/acl_internal_test.go | 50 ++++++------ packet/arp.go | 42 +++++----- packet/checksum_test.go | 5 +- packet/icmp6.go | 22 +++--- packet/lpm_test.go | 20 ++--- packet/packet.go | 94 +++++++++-------------- packet/packet_test.go | 5 +- packet/utils_for_test.go | 15 ++-- packet/vlan_test.go | 5 +- test/performance/perf_gen.go | 4 +- test/performance/perf_main.go | 5 +- test/performance/perf_seq.go | 3 +- test/stability/testCksum/testCksum.go | 8 +- test/stability/testMerge/testMerge.go | 5 +- 29 files changed, 283 insertions(+), 220 deletions(-) diff --git a/common/common.go b/common/common.go index bde0fc25..aee3abfa 100644 --- a/common/common.go +++ b/common/common.go @@ -7,10 +7,12 @@ package common import ( + "encoding/json" "fmt" "io" "log" "math" + "net" "os" "strconv" @@ -90,6 +92,85 @@ const ( IPv6VtcFlow = 0x60 // IPv6 version ) +type IPv4Address uint32 + +// BytesToIPv4 converts four element address to IPv4Address representation +func BytesToIPv4(a byte, b byte, c byte, d byte) IPv4Address { + return IPv4Address(d)<<24 | IPv4Address(c)<<16 | IPv4Address(b)<<8 | IPv4Address(a) +} + +// ArrayToIPv4 converts four element array to IPv4Address representation +func ArrayToIPv4(a [IPv4AddrLen]byte) IPv4Address { + return IPv4Address(a[3])<<24 | IPv4Address(a[2])<<16 | IPv4Address(a[1])<<8 | IPv4Address(a[0]) +} + +// SliceToIPv4 converts four element slice to IPv4Address representation +func SliceToIPv4(s []byte) IPv4Address { + return IPv4Address(s[3])<<24 | IPv4Address(s[2])<<16 | IPv4Address(s[1])<<8 | IPv4Address(s[0]) +} + +// IPv4ToBytes converts four element address to IPv4Address representation +func IPv4ToBytes(v IPv4Address) [IPv4AddrLen]byte { + return [IPv4AddrLen]uint8{byte(v), byte(v >> 8), byte(v >> 16), byte(v >> 24)} +} + +func (addr IPv4Address) String() string { + return fmt.Sprintf("%d.%d.%d.%d", byte(addr), byte(addr>>8), byte(addr>>16), byte(addr>>24)) +} + +// UnmarshalJSON parses IPv4 address. +func (out *IPv4Address) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + if ip := net.ParseIP(s); ip != nil { + ipv4 := ip.To4() + if ipv4 == nil { + return fmt.Errorf("Bad IPv4 address %s", s) + } + *out = BytesToIPv4(ipv4[0], ipv4[1], ipv4[2], ipv4[3]) + return nil + } + return fmt.Errorf("Failed to parse address %s", s) +} + +type IPv6Address [IPv6AddrLen]uint8 + +func (addr IPv6Address) String() string { + return fmt.Sprintf("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5], addr[6], addr[7], + addr[8], addr[9], addr[10], addr[11], + addr[12], addr[13], addr[14], addr[15]) +} + +// UnmarshalJSON parses IPv6 address. +func (out *IPv6Address) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + if ip := net.ParseIP(s); ip != nil { + ipv6 := ip.To16() + if ipv6 == nil { + return fmt.Errorf("Bad IPv6 address %s", s) + } + copy((*out)[:], ipv6) + return nil + } + return fmt.Errorf("Failed to parse address %s", s) +} + +type MACAddress [EtherAddrLen]uint8 + +// MACToString return MAC address like string +func (mac MACAddress) String() string { + return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) +} + // LogType - type of logging, used in flow package type LogType uint8 diff --git a/examples/antiddos/generatorForAntiDDoS.go b/examples/antiddos/generatorForAntiDDoS.go index d20a93dc..66ba8ed5 100644 --- a/examples/antiddos/generatorForAntiDDoS.go +++ b/examples/antiddos/generatorForAntiDDoS.go @@ -17,6 +17,7 @@ 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" ) @@ -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]common.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), @@ -115,7 +116,7 @@ func main() { // Function to use in generator func generatePacket(pkt *packet.Packet, context flow.UserContext) { - var address *uint32 + var address *common.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(common.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 common.IPv4Address, srcPort uint16) bool { for i := 0; i < goodDataListSize; i++ { if srcAddr == goodAddresses[i] && srcPort == goodPorts[i] { return true diff --git a/examples/gtpu.go b/examples/gtpu.go index b59f4dd7..094af4dd 100644 --- a/examples/gtpu.go +++ b/examples/gtpu.go @@ -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 != common.BytesToIPv4(55, 66, 77, 88) { // reject with wrong IP println("ERROR") return false @@ -78,8 +78,8 @@ func encap(current *packet.Packet, context flow.UserContext) bool { 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.SrcAddr = common.BytesToIPv4(11, 22, 33, 44) + ipv4.DstAddr = common.BytesToIPv4(55, 66, 77, 88) ipv4.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(ipv4)) current.ParseL4ForIPv4() @@ -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 = common.BytesToIPv4(1, 2, 3, 4) + ipv4.DstAddr = common.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..59033701 100644 --- a/examples/ipsec/ipsec_kernel.go +++ b/examples/ipsec/ipsec_kernel.go @@ -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 = common.BytesToIPv4(111, 22, 3, 0) + ipv4.DstAddr = common.BytesToIPv4(3, 22, 111, 0) ipv4.VersionIhl = 0x45 ipv4.NextProtoID = esp notDrop[i] = true @@ -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 = common.BytesToIPv4(111, 22, 3, 0) + ipv4.DstAddr = common.BytesToIPv4(3, 22, 111, 0) ipv4.VersionIhl = 0x45 ipv4.NextProtoID = esp diff --git a/examples/ipsec/stability/stability.go b/examples/ipsec/stability/stability.go index add0698c..b45c0dea 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/common" 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 = common.BytesToIPv4(111, 111, 111, 111) + ipv4.DstAddr = common.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/netlink.go b/examples/netlink.go index ff2a0269..2528f79d 100755 --- a/examples/netlink.go +++ b/examples/netlink.go @@ -24,10 +24,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 []common.IPv4Address // length of portToIp -var lenP2IP uint32 +var lenP2IP common.IPv4Address func main() { inport := flag.Uint("inport", 0, "port for receiver") @@ -59,23 +59,23 @@ func main() { func handler(current *packet.Packet, ctx flow.UserContext) { ipv4, _, _ := current.ParseAllKnownL3() if ipv4 != nil { - var next uint32 + var next common.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: ", common.IPv4ToBytes(portToIP[next])) } } } -func netToNffIPv4(netIP net.IP) uint32 { +func netToNffIPv4(netIP net.IP) common.IPv4Address { if netIP == nil || len(netIP) != 4 { return 0 } - return packet.BytesToIPv4(netIP[0], netIP[1], netIP[2], netIP[3]) + return common.BytesToIPv4(netIP[0], netIP[1], netIP[2], netIP[3]) } -func getIPAndDepth(netIP *net.IPNet) (uint32, uint8, error) { +func getIPAndDepth(netIP *net.IPNet) (common.IPv4Address, uint8, error) { var ( - ip uint32 + ip common.IPv4Address depth int ) if netIP != nil { diff --git a/examples/nffPktgen/generator/generator.go b/examples/nffPktgen/generator/generator.go index 355f52db..8706d89d 100644 --- a/examples/nffPktgen/generator/generator.go +++ b/examples/nffPktgen/generator/generator.go @@ -130,7 +130,7 @@ func generateARP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) { var SHA, THA [common.EtherAddrLen]uint8 SHA = [common.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.SwapBytesUint32(uint32(l3.SPA.Current)) + SPA := packet.SwapBytesIPv4Addr(common.IPv4Address(l3.SPA.Current)) getNextValue(&l3.SPA) if l3.Operation == packet.ARPRequest { if l3.Gratuitous { @@ -138,7 +138,7 @@ func generateARP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) { panic(fmt.Sprintf("InitGARPAnnouncementRequestPacket returned false")) } } else { - TPA := packet.SwapBytesUint32(uint32(l3.TPA.Current)) + TPA := packet.SwapBytesIPv4Addr(common.IPv4Address(l3.TPA.Current)) getNextValue(&l3.TPA) if !packet.InitARPRequestPacket(pkt, SHA, SPA, TPA) { panic(fmt.Sprintf("InitARPRequestPacket returned false")) @@ -152,7 +152,7 @@ func generateARP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) { } else { THA = [common.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.SwapBytesUint32(uint32(l3.TPA.Current)) + TPA := packet.SwapBytesIPv4Addr(common.IPv4Address(l3.TPA.Current)) getNextValue(&l3.TPA) if !packet.InitARPReplyPacket(pkt, SHA, THA, SPA, TPA) { panic(fmt.Sprintf("InitARPReplyPacket returned false")) @@ -263,8 +263,8 @@ func fillICMPHdr(pkt *packet.Packet, l4 *ICMPConfig, rnd *rand.Rand) { func fillIPv4Hdr(pkt *packet.Packet, l3 *IPv4Config) { pktIP := (*packet.IPv4Hdr)(pkt.L3) - pktIP.SrcAddr = packet.SwapBytesUint32(uint32(l3.SAddr.Current)) - pktIP.DstAddr = packet.SwapBytesUint32(uint32(l3.DAddr.Current)) + pktIP.SrcAddr = packet.SwapBytesIPv4Addr(common.IPv4Address(l3.SAddr.Current)) + pktIP.DstAddr = packet.SwapBytesIPv4Addr(common.IPv4Address(l3.DAddr.Current)) getNextValue(&l3.DAddr) getNextValue(&l3.SAddr) } diff --git a/examples/pingReplay.go b/examples/pingReplay.go index 71053972..570d7cfe 100644 --- a/examples/pingReplay.go +++ b/examples/pingReplay.go @@ -2,6 +2,7 @@ package main import ( "flag" + "github.com/intel-go/nff-go/common" "github.com/intel-go/nff-go/flow" ) @@ -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), common.IPv4Address(20)<<24|common.IPv4Address(20)<<16|common.IPv4Address(20)<<8|common.IPv4Address(20))) flow.CheckFatal(flow.DealARPICMP(inputFlow)) flow.CheckFatal(flow.SetStopper(inputFlow)) diff --git a/examples/tutorial/step10.go b/examples/tutorial/step10.go index 0b33345e..787d1f8d 100644 --- a/examples/tutorial/step10.go +++ b/examples/tutorial/step10.go @@ -45,8 +45,8 @@ func myHandler(curV []*packet.Packet, mask *[vecSize]bool, ctx flow.UserContext) cur := curV[i] cur.EncapsulateHead(common.EtherLen, common.IPv4MinLen) cur.ParseL3() - cur.GetIPv4NoCheck().SrcAddr = packet.BytesToIPv4(111, 22, 3, 0) - cur.GetIPv4NoCheck().DstAddr = packet.BytesToIPv4(3, 22, 111, 0) + cur.GetIPv4NoCheck().SrcAddr = common.BytesToIPv4(111, 22, 3, 0) + cur.GetIPv4NoCheck().DstAddr = common.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..c980fbed 100644 --- a/examples/tutorial/step11.go +++ b/examples/tutorial/step11.go @@ -45,8 +45,8 @@ func myHandler(curV []*packet.Packet, mask *[vecSize]bool, ctx flow.UserContext) cur := curV[i] cur.EncapsulateHead(common.EtherLen, common.IPv4MinLen) cur.ParseL3() - cur.GetIPv4NoCheck().SrcAddr = packet.BytesToIPv4(111, 22, 3, 0) - cur.GetIPv4NoCheck().DstAddr = packet.BytesToIPv4(3, 22, 111, 0) + cur.GetIPv4NoCheck().SrcAddr = common.BytesToIPv4(111, 22, 3, 0) + cur.GetIPv4NoCheck().DstAddr = common.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..5e64209c 100644 --- a/examples/tutorial/step9.go +++ b/examples/tutorial/step9.go @@ -40,8 +40,8 @@ func mySplitter(cur *packet.Packet, ctx flow.UserContext) uint { func myHandler(cur *packet.Packet, ctx flow.UserContext) { cur.EncapsulateHead(common.EtherLen, common.IPv4MinLen) cur.ParseL3() - cur.GetIPv4NoCheck().SrcAddr = packet.BytesToIPv4(111, 22, 3, 0) - cur.GetIPv4NoCheck().DstAddr = packet.BytesToIPv4(3, 22, 111, 0) + cur.GetIPv4NoCheck().SrcAddr = common.BytesToIPv4(111, 22, 3, 0) + cur.GetIPv4NoCheck().DstAddr = common.BytesToIPv4(3, 22, 111, 0) cur.GetIPv4NoCheck().VersionIhl = 0x45 cur.GetIPv4NoCheck().NextProtoID = 0x04 } diff --git a/flow/flow.go b/flow/flow.go index b28fe9e5..7f99139b 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -43,7 +43,7 @@ import ( var openFlowsNumber = uint32(0) var createdPorts []port -var portPair map[uint32](*port) +var portPair map[common.IPv4Address](*port) var schedState *scheduler var vEach [10][burstSize]uint8 var devices map[string]int @@ -424,7 +424,7 @@ type port struct { willKNI bool // will this port has assigned KNI device KNICoreIndex int port uint16 - MAC [common.EtherAddrLen]uint8 + MAC common.MACAddress InIndex int32 sendRings low.Rings } @@ -586,7 +586,7 @@ func SystemInit(args *Config) error { createdPorts[i].InIndex = maxInIndex } } - portPair = make(map[uint32](*port)) + portPair = make(map[common.IPv4Address](*port)) devices = make(map[string]int) // Init scheduler common.LogTitle(common.Initialization, "------------***------ Initializing scheduler -----***------------") @@ -618,7 +618,7 @@ func SystemInitPortsAndMemory() error { } } createdPorts[i].MAC = GetPortMACAddress(createdPorts[i].port) - common.LogDebug(common.Initialization, "Port", createdPorts[i].port, "MAC address:", packet.MACToString(createdPorts[i].MAC)) + common.LogDebug(common.Initialization, "Port", createdPorts[i].port, "MAC address:", createdPorts[i].MAC.String()) } common.LogTitle(common.Initialization, "------------***------ Starting FlowFunctions -----***------------") // Init low performance mempool @@ -1091,7 +1091,7 @@ func GetNameByPort(port uint16) (string, error) { // SetIPForPort sets IP for specified port if it was created. Not thread safe. // Return error if requested port isn't exist or wasn't previously requested. -func SetIPForPort(port uint16, ip uint32) error { +func SetIPForPort(port uint16, ip common.IPv4Address) error { for i := range createdPorts { if createdPorts[i].port == port && createdPorts[i].wasRequested { portPair[ip] = &createdPorts[i] diff --git a/flow/predefined.go b/flow/predefined.go index 3eea7da1..6cca5f44 100644 --- a/flow/predefined.go +++ b/flow/predefined.go @@ -21,7 +21,7 @@ func handleARPICMPRequests(current *packet.Packet, context UserContext) bool { return false } - port := portPair[packet.ArrayToIPv4(arp.TPA)] + port := portPair[common.ArrayToIPv4(arp.TPA)] if port == nil { return false } @@ -31,7 +31,7 @@ func handleARPICMPRequests(current *packet.Packet, context UserContext) bool { if err != nil { common.LogFatal(common.Debug, err) } - packet.InitARPReplyPacket(answerPacket, port.MAC, arp.SHA, packet.ArrayToIPv4(arp.TPA), packet.ArrayToIPv4(arp.SPA)) + packet.InitARPReplyPacket(answerPacket, port.MAC, arp.SHA, common.ArrayToIPv4(arp.TPA), common.ArrayToIPv4(arp.SPA)) answerPacket.SendPacket(port.port) return false diff --git a/low/low.go b/low/low.go index 3461cddc..9686dfb5 100644 --- a/low/low.go +++ b/low/low.go @@ -718,12 +718,12 @@ func CreateLPM(name string, socket uint8, maxRules uint32, numberTbl8 uint32, tb } // AddLPMRule adds one rule to LPM table -func AddLPMRule(lpm unsafe.Pointer, ip uint32, depth uint8, nextHop uint32) int { +func AddLPMRule(lpm unsafe.Pointer, ip common.IPv4Address, depth uint8, nextHop common.IPv4Address) int { return int(C.lpm_add(lpm, C.uint32_t(ip), C.uint8_t(depth), C.uint32_t(nextHop))) } // DeleteLPMRule removes one rule from LPM table -func DeleteLPMRule(lpm unsafe.Pointer, ip uint32, depth uint8) int { +func DeleteLPMRule(lpm unsafe.Pointer, ip common.IPv4Address, depth uint8) int { return int(C.lpm_delete(lpm, C.uint32_t(ip), C.uint8_t(depth))) } diff --git a/packet/acl.go b/packet/acl.go index a38350bb..1593f837 100644 --- a/packet/acl.go +++ b/packet/acl.go @@ -396,8 +396,8 @@ func parseRuleResult(rule string) (uint, error) { } } -func parseAddr4(addr *net.IPNet) (uint32, uint32) { - return binary.LittleEndian.Uint32(addr.IP), binary.LittleEndian.Uint32(addr.Mask) +func parseAddr4(addr *net.IPNet) (common.IPv4Address, common.IPv4Address) { + return common.IPv4Address(binary.LittleEndian.Uint32(addr.IP)), common.IPv4Address(binary.LittleEndian.Uint32(addr.Mask)) } func parseAddr6(addr *net.IPNet) ([16]uint8, [16]uint8) { @@ -413,8 +413,8 @@ type l2Rules struct { OutputNumber uint DAddrNotAny bool SAddrNotAny bool - DAddr [6]uint8 - SAddr [6]uint8 + DAddr common.MACAddress + SAddr common.MACAddress IDMask uint16 ID uint16 } @@ -431,19 +431,19 @@ type l4Rules struct { type l3Rules4 struct { OutputNumber uint - SrcAddr uint32 - DstAddr uint32 - SrcMask uint32 - DstMask uint32 + SrcAddr common.IPv4Address + DstAddr common.IPv4Address + SrcMask common.IPv4Address + DstMask common.IPv4Address L4 l4Rules } type l3Rules6 struct { OutputNumber uint - SrcAddr [16]uint8 - DstAddr [16]uint8 - SrcMask [16]uint8 - DstMask [16]uint8 + SrcAddr common.IPv6Address + DstAddr common.IPv6Address + SrcMask common.IPv6Address + DstMask common.IPv6Address L4 l4Rules } diff --git a/packet/acl_internal_test.go b/packet/acl_internal_test.go index 68375344..dac61b63 100644 --- a/packet/acl_internal_test.go +++ b/packet/acl_internal_test.go @@ -59,6 +59,8 @@ import ( "os" "reflect" "testing" + + "github.com/intel-go/nff-go/common" ) // Data to generate L2 rules @@ -70,12 +72,12 @@ var rulesL2Ctxt = rawL2RuleTestCtxt{ {"", 0}, // case only for ORIG }, srcs: []macAddrTest{ // {rawaddr, ground truth addr info {macaddr, addrNotAny}} - {"ANY", gtMacAddr{[6]uint8{0, 0, 0, 0, 0, 0}, false}}, + {"ANY", gtMacAddr{common.MACAddress{0, 0, 0, 0, 0, 0}, false}}, {"00:11:22:33:44:55", gtMacAddr{[6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, true}}, }, dsts: []macAddrTest{ // {rawaddr, ground truth addr info {macaddr, addrNotAny}} - {"ANY", gtMacAddr{[6]uint8{0, 0, 0, 0, 0, 0}, false}}, - {"01:11:21:31:41:51", gtMacAddr{[6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, true}}, + {"ANY", gtMacAddr{common.MACAddress{0, 0, 0, 0, 0, 0}, false}}, + {"01:11:21:31:41:51", gtMacAddr{common.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, true}}, }, ids: []idTest{ // {rawid, ground truth {id, idmask}} {"ANY", gtID{0, 0x0000}}, @@ -98,40 +100,40 @@ var rulesL3Ctxt = rawL3RuleTestCtxt{ srcs6: []Addr6Test{ // {rawaddr, ground truth addr info {macaddr, addrNotAny}} {"ANY", gtAddr6{ - [16]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - [16]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, {"::/0", gtAddr6{ - [16]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - [16]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, {"dead::beef/16", gtAddr6{ - [16]uint8{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - [16]uint8{0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, }, dsts6: []Addr6Test{ // {rawaddr, ground truth addr info} {"ANY", gtAddr6{ - [16]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - [16]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, {"::/0", gtAddr6{ - [16]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - [16]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, {"dead::beef/128", gtAddr6{ - [16]uint8{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbe, 0xef}, - [16]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + common.IPv6Address{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbe, 0xef}, + common.IPv6Address{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, }, }, }, @@ -1342,13 +1344,13 @@ type Addr6Test struct { } type gtAddr4 struct { - addr uint32 - mask uint32 + addr common.IPv4Address + mask common.IPv4Address } type gtAddr6 struct { - addr [16]uint8 - mask [16]uint8 + addr common.IPv6Address + mask common.IPv6Address } type portTest struct { @@ -1424,19 +1426,19 @@ type IDMask16 struct { } type Addr4Mask struct { - addr uint32 - msk uint32 + addr common.IPv4Address + msk common.IPv4Address ok bool } type Addr6Mask struct { - addr [16]uint8 - msk [16]uint8 + addr common.IPv6Address + msk common.IPv6Address ok bool } type MacAddr struct { - addr [6]uint8 + addr common.MACAddress addrNotAny bool ok bool } diff --git a/packet/arp.go b/packet/arp.go index ea8a87b2..b983ec1d 100644 --- a/packet/arp.go +++ b/packet/arp.go @@ -13,16 +13,16 @@ import ( // ARPHdr is protocol structure used in Address Resolution Protocol // for IPv4 to MAC mapping type ARPHdr struct { - HType uint16 // Hardware type, e.g. 1 for Ethernet - PType uint16 // Protocol type, e.g. 0x0800 for IPv4 - HLen uint8 // Hardware address length, e.g. 6 for MAC length - PLen uint8 // Protocol address length, e.g. 4 for IPv4 address length - Operation uint16 // Operation type, see ARP constants - SHA [common.EtherAddrLen]uint8 // Sender hardware address (sender MAC address) - SPA [common.IPv4AddrLen]uint8 // Sender protocol address (sender IPv4 address) + HType uint16 // Hardware type, e.g. 1 for Ethernet + PType uint16 // Protocol type, e.g. 0x0800 for IPv4 + HLen uint8 // Hardware address length, e.g. 6 for MAC length + PLen uint8 // Protocol address length, e.g. 4 for IPv4 address length + Operation uint16 // Operation type, see ARP constants + SHA common.MACAddress // Sender hardware address (sender MAC address) + SPA [common.IPv4AddrLen]uint8 // Sender protocol address (sender IPv4 address) // array is used to avoid alignment (compiler alignes uint32 on 4 bytes) - THA [common.EtherAddrLen]uint8 // Target hardware address (target MAC address) - TPA [common.IPv4AddrLen]uint8 // Target protocol address (target IPv4 address) + THA common.MACAddress // Target hardware address (target MAC address) + TPA [common.IPv4AddrLen]uint8 // Target protocol address (target IPv4 address) // array is used to avoid alignment (compiler alignes uint32 on 4 bytes) } @@ -75,7 +75,7 @@ func initARPCommonData(packet *Packet) bool { // specifies IP address for host which request is sent // for. Destination MAC address in L2 Ethernet header is set to // FF:FF:FF:FF:FF:FF (broadcast) and source address is set to SHA. -func InitARPRequestPacket(packet *Packet, SHA [common.EtherAddrLen]uint8, SPA, TPA uint32) bool { +func InitARPRequestPacket(packet *Packet, SHA common.MACAddress, SPA, TPA common.IPv4Address) bool { if !initARPCommonData(packet) { common.LogWarning(common.Debug, "InitARPRequestPacket: failed to fill common data") return false @@ -85,9 +85,9 @@ func InitARPRequestPacket(packet *Packet, SHA [common.EtherAddrLen]uint8, SPA, T arp := packet.GetARPNoCheck() arp.Operation = SwapBytesUint16(ARPRequest) arp.SHA = SHA - arp.SPA = IPv4ToBytes(SPA) + arp.SPA = common.IPv4ToBytes(SPA) arp.THA = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - arp.TPA = IPv4ToBytes(TPA) + arp.TPA = common.IPv4ToBytes(TPA) return true } @@ -96,7 +96,7 @@ func InitARPRequestPacket(packet *Packet, SHA [common.EtherAddrLen]uint8, SPA, T // TPA specify target MAC and IP addresses. Destination MAC address // in L2 Ethernet header is set to THA and source address is set to // SHA. -func InitARPReplyPacket(packet *Packet, SHA, THA [common.EtherAddrLen]uint8, SPA, TPA uint32) bool { +func InitARPReplyPacket(packet *Packet, SHA, THA common.MACAddress, SPA, TPA common.IPv4Address) bool { if !initARPCommonData(packet) { common.LogWarning(common.Debug, "InitARPRequestPacket: failed to fill common data") return false @@ -106,9 +106,9 @@ func InitARPReplyPacket(packet *Packet, SHA, THA [common.EtherAddrLen]uint8, SPA arp := packet.GetARPNoCheck() arp.Operation = SwapBytesUint16(ARPReply) arp.SHA = SHA - arp.SPA = IPv4ToBytes(SPA) + arp.SPA = common.IPv4ToBytes(SPA) arp.THA = THA - arp.TPA = IPv4ToBytes(TPA) + arp.TPA = common.IPv4ToBytes(TPA) return true } @@ -118,7 +118,7 @@ func InitARPReplyPacket(packet *Packet, SHA, THA [common.EtherAddrLen]uint8, SPA // SPA specify sender MAC and IP addresses, TPA is set to the value of // SPA. Destination MAC address in L2 Ethernet header is set to // FF:FF:FF:FF:FF:FF (broadcast) and source address is set to SHA. -func InitGARPAnnouncementRequestPacket(packet *Packet, SHA [common.EtherAddrLen]uint8, SPA uint32) bool { +func InitGARPAnnouncementRequestPacket(packet *Packet, SHA common.MACAddress, SPA common.IPv4Address) bool { if !initARPCommonData(packet) { common.LogWarning(common.Debug, "InitARPRequestPacket: failed to fill common data") return false @@ -128,9 +128,9 @@ func InitGARPAnnouncementRequestPacket(packet *Packet, SHA [common.EtherAddrLen] arp := packet.GetARPNoCheck() arp.Operation = SwapBytesUint16(ARPRequest) arp.SHA = SHA - arp.SPA = IPv4ToBytes(SPA) + arp.SPA = common.IPv4ToBytes(SPA) arp.THA = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - arp.TPA = IPv4ToBytes(SPA) + arp.TPA = common.IPv4ToBytes(SPA) return true } @@ -140,7 +140,7 @@ func InitGARPAnnouncementRequestPacket(packet *Packet, SHA [common.EtherAddrLen] // to zeroes (according to RFC 5227). Destination MAC address in L2 Ethernet header is set // to FF:FF:FF:FF:FF:FF (broadcast) and source address is set // to SHA. -func InitGARPAnnouncementReplyPacket(packet *Packet, SHA [common.EtherAddrLen]uint8, SPA uint32) bool { +func InitGARPAnnouncementReplyPacket(packet *Packet, SHA common.MACAddress, SPA common.IPv4Address) bool { if !initARPCommonData(packet) { common.LogWarning(common.Debug, "InitARPRequestPacket: failed to fill common data") return false @@ -150,8 +150,8 @@ func InitGARPAnnouncementReplyPacket(packet *Packet, SHA [common.EtherAddrLen]ui arp := packet.GetARPNoCheck() arp.Operation = SwapBytesUint16(ARPReply) arp.SHA = SHA - arp.SPA = IPv4ToBytes(SPA) + arp.SPA = common.IPv4ToBytes(SPA) arp.THA = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - arp.TPA = IPv4ToBytes(SPA) + arp.TPA = common.IPv4ToBytes(SPA) return true } diff --git a/packet/checksum_test.go b/packet/checksum_test.go index 042751b5..ed778093 100644 --- a/packet/checksum_test.go +++ b/packet/checksum_test.go @@ -5,7 +5,6 @@ package packet import ( - "encoding/binary" "github.com/intel-go/nff-go/common" "net" "testing" @@ -159,8 +158,8 @@ func TestCalculateIPv6ICMPChecksum(t *testing.T) { func initIPv4AddrsLocal(pkt *Packet) { ipv4 := pkt.GetIPv4() - ipv4.SrcAddr = binary.LittleEndian.Uint32(net.ParseIP("131.151.32.21").To4()) - ipv4.DstAddr = binary.LittleEndian.Uint32(net.ParseIP("131.151.32.129").To4()) + ipv4.SrcAddr = common.SliceToIPv4(net.ParseIP("131.151.32.21").To4()) + ipv4.DstAddr = common.SliceToIPv4(net.ParseIP("131.151.32.129").To4()) ipv4.HdrChecksum = 0 } diff --git a/packet/icmp6.go b/packet/icmp6.go index 7b7db94e..24eca73c 100644 --- a/packet/icmp6.go +++ b/packet/icmp6.go @@ -38,13 +38,13 @@ var ( type ICMPv6NDSourceLinkLayerAddressOption struct { Type uint8 Length uint8 - LinkLayerAddress [common.EtherAddrLen]uint8 + LinkLayerAddress common.MACAddress } type ICMPv6NDTargetLinkLayerAddressOption struct { Type uint8 Length uint8 - LinkLayerAddress [common.EtherAddrLen]uint8 + LinkLayerAddress common.MACAddress } type ICMPv6NDPrefixInformationOption struct { @@ -55,7 +55,7 @@ type ICMPv6NDPrefixInformationOption struct { ValidLifetime uint32 PreferredLifetime uint32 Reserved2 uint32 - Prefix [common.IPv6AddrLen]uint8 + Prefix common.IPv6Address } type ICMPv6NDRedirectedHeaderOption struct { @@ -71,11 +71,11 @@ type ICMPv6NDMTUOption struct { } type ICMPv6NeighborSolicitationMessage struct { - TargetAddr [common.IPv6AddrLen]uint8 + TargetAddr common.IPv6Address } type ICMPv6NeighborAdvertisementMessage struct { - TargetAddr [common.IPv6AddrLen]uint8 + TargetAddr common.IPv6Address } // GetICMPv6NeighborSolicitationMessage returns pointer to ICMPv6 @@ -126,7 +126,7 @@ func (packet *Packet) GetICMPv6NDTargetLinkLayerAddressOption(msgLength uint) *I // CalculateIPv6LinkLocalAddrForMAC generates IPv6 link local address // based on interface MAC address. -func CalculateIPv6LinkLocalAddrForMAC(llAddr *[common.IPv6AddrLen]uint8, mac [common.EtherAddrLen]uint8) { +func CalculateIPv6LinkLocalAddrForMAC(llAddr *common.IPv6Address, mac common.MACAddress) { copy((*llAddr)[:], ipv6LinkLocalPrefix) (*llAddr)[8] = mac[0] ^ 0x02 (*llAddr)[9] = mac[1] @@ -142,14 +142,14 @@ func CalculateIPv6LinkLocalAddrForMAC(llAddr *[common.IPv6AddrLen]uint8, mac [co // that other hosts use to solicit its MAC address. This address is // used as destination for all Neighbor Solicitation ICMPv6 messages // and NAT should answer packets coming to it. -func CalculateIPv6MulticastAddrForDstIP(muticastAddr *[common.IPv6AddrLen]uint8, dstIP [common.IPv6AddrLen]uint8) { +func CalculateIPv6MulticastAddrForDstIP(muticastAddr *common.IPv6Address, dstIP common.IPv6Address) { copy((*muticastAddr)[:], ipv6LinkLocalMulticastPrefix) (*muticastAddr)[13] = dstIP[13] (*muticastAddr)[14] = dstIP[14] (*muticastAddr)[15] = dstIP[15] } -func CalculateIPv6BroadcastMACForDstMulticastIP(dstMAC *[common.EtherAddrLen]uint8, dstIP [common.IPv6AddrLen]uint8) { +func CalculateIPv6BroadcastMACForDstMulticastIP(dstMAC *common.MACAddress, dstIP common.IPv6Address) { copy((*dstMAC)[:], ipv6EtherMulticastPrefix) (*dstMAC)[2] = dstIP[12] (*dstMAC)[3] = dstIP[13] @@ -160,10 +160,10 @@ func CalculateIPv6BroadcastMACForDstMulticastIP(dstMAC *[common.EtherAddrLen]uin // InitICMPv6NeighborSolicitationPacket allocates and initializes // ICMPv6 Neighbor Solicitation request message packet with source MAC // and IPv6 address and target IPv6 address. -func InitICMPv6NeighborSolicitationPacket(packet *Packet, srcMAC [common.EtherAddrLen]uint8, srcIP, dstIP [common.IPv6AddrLen]uint8) { +func InitICMPv6NeighborSolicitationPacket(packet *Packet, srcMAC common.MACAddress, srcIP, dstIP common.IPv6Address) { InitEmptyIPv6ICMPPacket(packet, ICMPv6NeighborSolicitationMessageSize+ICMPv6NDSourceLinkLayerAddressOptionSize) - var targetMulticastAddr [common.IPv6AddrLen]uint8 + var targetMulticastAddr common.IPv6Address CalculateIPv6MulticastAddrForDstIP(&targetMulticastAddr, dstIP) // Fill up L2 @@ -194,7 +194,7 @@ func InitICMPv6NeighborSolicitationPacket(packet *Packet, srcMAC [common.EtherAd // InitICMPv6NeighborAdvertisementPacket allocates and initializes // ICMPv6 Neighbor Advertisement answer message packet with source MAC // and IPv6 address and target IPv6 address. -func InitICMPv6NeighborAdvertisementPacket(packet *Packet, srcMAC, dstMAC [common.EtherAddrLen]uint8, srcIP, dstIP [common.IPv6AddrLen]uint8) { +func InitICMPv6NeighborAdvertisementPacket(packet *Packet, srcMAC, dstMAC common.MACAddress, srcIP, dstIP common.IPv6Address) { InitEmptyIPv6ICMPPacket(packet, ICMPv6NeighborAdvertisementMessageSize+ICMPv6NDTargetLinkLayerAddressOptionSize) // Fill up L2 diff --git a/packet/lpm_test.go b/packet/lpm_test.go index 8413cd57..7f99565c 100644 --- a/packet/lpm_test.go +++ b/packet/lpm_test.go @@ -9,6 +9,8 @@ import ( "math/rand" "testing" "time" + + "github.com/intel-go/nff-go/common" ) func init() { @@ -16,8 +18,8 @@ func init() { rand.Seed(time.Now().UTC().UnixNano()) } -var zero uint32 = 0 -var next uint32 +var zero common.IPv4Address = 0 +var next common.IPv4Address var stepM = 1000 var stepN = 10 @@ -28,13 +30,13 @@ func TestOneRule(t *testing.T) { for i := 0; i < stepM; i++ { ip_number := 1 + rand.Intn(32) mask_len := uint8(1 + rand.Intn(32)) - next_hop := uint32(rand.Intn(100)) + next_hop := common.IPv4Address(rand.Intn(100)) // Construct ip ip := constructIP(ip_number) // Construct mask mask := zero - for u := zero; u < uint32(mask_len); u++ { + for u := zero; u < common.IPv4Address(mask_len); u++ { mask = mask | (1 << (31 - u)) } @@ -132,8 +134,8 @@ func TestMultipleRules(t *testing.T) { lpm.Free() } -func constructIP(ip_number int) uint32 { - var ip uint32 +func constructIP(ip_number int) common.IPv4Address { + var ip common.IPv4Address if ip_number < 16 { ip = zero for j := 0; j < ip_number; j++ { @@ -156,15 +158,15 @@ func constructIP(ip_number int) uint32 { return ip } -func testIP(ip uint32, mask_len uint8) (int, int, []uint32, []uint32) { +func testIP(ip common.IPv4Address, mask_len uint8) (int, int, []common.IPv4Address, []common.IPv4Address) { right := int(math.Pow(2, float64(32-mask_len))) wrong := int(math.Pow(2, float64(mask_len)) - 1) rightN := rand.Intn(right)%stepK + 1 wrongN := rand.Intn(wrong)%stepK + 1 - rightIP := make([]uint32, rightN, rightN) - wrongIP := make([]uint32, wrongN, wrongN) + rightIP := make([]common.IPv4Address, rightN, rightN) + wrongIP := make([]common.IPv4Address, wrongN, wrongN) rightIP[0] = ip for i := 1; i < rightN; i++ { diff --git a/packet/packet.go b/packet/packet.go index 90f4a72c..512d1f03 100644 --- a/packet/packet.go +++ b/packet/packet.go @@ -69,9 +69,9 @@ func init() { // EtherHdr L2 header from DPDK: lib/librte_ether/rte_ehter.h type EtherHdr struct { - DAddr [EtherAddrLen]uint8 // Destination address - SAddr [EtherAddrLen]uint8 // Source address - EtherType uint16 // Frame type + DAddr MACAddress // Destination address + SAddr MACAddress // Source address + EtherType uint16 // Frame type } func (hdr *EtherHdr) String() string { @@ -80,8 +80,8 @@ Ethernet Source: %s Ethernet Destination: %s `, hdr.EtherType, getEtherTypeName(hdr.EtherType), - MACToString(hdr.SAddr), - MACToString(hdr.DAddr)) + hdr.SAddr.String(), + hdr.DAddr.String()) } var ( @@ -102,59 +102,46 @@ func getEtherTypeName(et uint16) string { return ret } -// MACToString return MAC address like string -func MACToString(mac [EtherAddrLen]uint8) string { - return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) -} - // IPv4Hdr L3 header from DPDK: lib/librte_net/rte_ip.h type IPv4Hdr struct { - VersionIhl uint8 // version and header length - TypeOfService uint8 // type of service - TotalLength uint16 // length of packet - PacketID uint16 // packet ID - FragmentOffset uint16 // fragmentation offset - TimeToLive uint8 // time to live - NextProtoID uint8 // protocol ID - HdrChecksum uint16 // header checksum - SrcAddr uint32 // source address - DstAddr uint32 // destination address + VersionIhl uint8 // version and header length + TypeOfService uint8 // type of service + TotalLength uint16 // length of packet + PacketID uint16 // packet ID + FragmentOffset uint16 // fragmentation offset + TimeToLive uint8 // time to live + NextProtoID uint8 // protocol ID + HdrChecksum uint16 // header checksum + SrcAddr IPv4Address // source address + DstAddr IPv4Address // destination address } -func IPv4ToString(addr uint32) string { - return fmt.Sprintf("%d.%d.%d.%d", byte(addr), byte(addr>>8), byte(addr>>16), byte(addr>>24)) +func IPv4ArrayToString(addr [IPv4AddrLen]uint8) string { + return fmt.Sprintf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]) } func (hdr *IPv4Hdr) String() string { r0 := " L3 protocol: IPv4\n" - r1 := " IPv4 Source: " + IPv4ToString(hdr.SrcAddr) + "\n" - r2 := " IPv4 Destination: " + IPv4ToString(hdr.DstAddr) + "\n" + r1 := " IPv4 Source: " + hdr.SrcAddr.String() + "\n" + r2 := " IPv4 Destination: " + hdr.DstAddr.String() + "\n" return r0 + r1 + r2 } // IPv6Hdr L3 header from DPDK: lib/librte_net/rte_ip.h type IPv6Hdr struct { - VtcFlow uint32 // IP version, traffic class & flow label - PayloadLen uint16 // IP packet length - includes sizeof(ip_header) - Proto uint8 // Protocol, next header - HopLimits uint8 // Hop limits - SrcAddr [IPv6AddrLen]uint8 // IP address of source host - DstAddr [IPv6AddrLen]uint8 // IP address of destination host(s) -} - -func IPv6ToString(addr [IPv6AddrLen]uint8) string { - return fmt.Sprintf("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", - addr[0], addr[1], addr[2], addr[3], - addr[4], addr[5], addr[6], addr[7], - addr[8], addr[9], addr[10], addr[11], - addr[12], addr[13], addr[14], addr[15]) + VtcFlow uint32 // IP version, traffic class & flow label + PayloadLen uint16 // IP packet length - includes sizeof(ip_header) + Proto uint8 // Protocol, next header + HopLimits uint8 // Hop limits + SrcAddr IPv6Address // IP address of source host + DstAddr IPv6Address // IP address of destination host(s) } func (hdr *IPv6Hdr) String() string { return fmt.Sprintf(` L3 protocol: IPv6 IPv6 Source: %s IPv6 Destination %s -`, IPv6ToString(hdr.SrcAddr), IPv6ToString(hdr.DstAddr)) +`, hdr.SrcAddr.String(), hdr.DstAddr.String()) } // TCPHdr L4 header from DPDK: lib/librte_net/rte_tcp.h @@ -717,6 +704,10 @@ func SwapBytesUint32(x uint32) uint32 { return ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24) } +func SwapBytesIPv4Addr(x IPv4Address) IPv4Address { + return ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24) +} + // GetRawPacketBytes returns all bytes from this packet. Not zero-copy. func (packet *Packet) GetRawPacketBytes() []byte { return low.GetRawPacketBytesMbuf(packet.CMbuf) @@ -817,21 +808,6 @@ func (packet *Packet) PacketBytesChange(start uint, bytes []byte) bool { return true } -// BytesToIPv4 converts four element address to uint32 representation -func BytesToIPv4(a byte, b byte, c byte, d byte) uint32 { - return uint32(d)<<24 | uint32(c)<<16 | uint32(b)<<8 | uint32(a) -} - -// ArrayToIPv4 converts four element array to uint32 representation -func ArrayToIPv4(a [IPv4AddrLen]byte) uint32 { - return uint32(a[3])<<24 | uint32(a[2])<<16 | uint32(a[1])<<8 | uint32(a[0]) -} - -// IPv4ToBytes converts four element address to uint32 representation -func IPv4ToBytes(v uint32) [IPv4AddrLen]byte { - return [IPv4AddrLen]uint8{byte(v), byte(v >> 8), byte(v >> 16), byte(v >> 24)} -} - // NewPacket shouldn't be used for performance critical allocations. // Allocate mbufs one by one is very inefficient. // FastGenerate or copy functions give developer a packet from previously bulk allocated set @@ -862,8 +838,8 @@ func SetNonPerfMempool(m *low.Mempool) { } type LPM struct { - tbl24 *([MaxLength]uint32) - tbl8 *([MaxLength]uint32) + tbl24 *([MaxLength]IPv4Address) + tbl8 *([MaxLength]IPv4Address) lpm unsafe.Pointer //C.struct_rte_lpm } @@ -884,7 +860,7 @@ func CreateLPM(name string, socket uint8, maxRules uint32, numberTbl8 uint32) *L // Heavily based on DPDK rte_lpm_lookup with constants from there // No error checking (lpm == NULL or nextHop == NULL) due to performance // User should check it manually -func (lpm *LPM) Lookup(ip uint32, nextHop *uint32) bool { +func (lpm *LPM) Lookup(ip IPv4Address, nextHop *IPv4Address) bool { tbl24_index := ip >> 8 tbl_entry := (*lpm.tbl24)[tbl24_index] // Copy tbl24 entry @@ -903,13 +879,13 @@ func (lpm *LPM) Lookup(ip uint32, nextHop *uint32) bool { // Add adds longest prefix match rule with specified ip, depth and nextHop // inside LPM table. Returns 0 if success and negative value otherwise -func (lpm *LPM) Add(ip uint32, depth uint8, nextHop uint32) int { +func (lpm *LPM) Add(ip IPv4Address, depth uint8, nextHop IPv4Address) int { return low.AddLPMRule(lpm.lpm, ip, depth, nextHop) } // Delete removes longest prefix match rule with diven ip and depth from // LPM table. Returns 0 if success and negative value otherwise -func (lpm *LPM) Delete(ip uint32, depth uint8) int { +func (lpm *LPM) Delete(ip IPv4Address, depth uint8) int { return low.DeleteLPMRule(lpm.lpm, ip, depth) } diff --git a/packet/packet_test.go b/packet/packet_test.go index 4b11b21e..1acb7599 100644 --- a/packet/packet_test.go +++ b/packet/packet_test.go @@ -6,7 +6,6 @@ package packet import ( "bytes" - "encoding/binary" "encoding/hex" "net" "reflect" @@ -458,8 +457,8 @@ func TestInitEmptyIPv4Packet(t *testing.T) { InitEmptyIPv4Packet(pkt, testPlSize) dst := net.ParseIP("128.9.9.5").To4() src := net.ParseIP("127.0.0.1").To4() - pkt.GetIPv4().DstAddr = binary.LittleEndian.Uint32([]byte(dst)) - pkt.GetIPv4().SrcAddr = binary.LittleEndian.Uint32([]byte(src)) + pkt.GetIPv4().DstAddr = SliceToIPv4(dst) + pkt.GetIPv4().SrcAddr = SliceToIPv4(src) ptrData := (*Packetdata)(pkt.Data) ptrData.F1 = 0xddff ptrData.F2 = 0xaabb diff --git a/packet/utils_for_test.go b/packet/utils_for_test.go index bb8c5e70..1006e11c 100644 --- a/packet/utils_for_test.go +++ b/packet/utils_for_test.go @@ -3,7 +3,6 @@ package packet import ( - "encoding/binary" "fmt" "log" "net" @@ -96,22 +95,22 @@ func getIPv6ICMPTestPacket() *Packet { func getARPRequestTestPacket() *Packet { pkt := getPacket() - sha := [common.EtherAddrLen]byte{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} - spa := binary.LittleEndian.Uint32(net.ParseIP("127.0.0.1").To4()) - tpa := binary.LittleEndian.Uint32(net.ParseIP("128.9.9.5").To4()) + sha := common.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} + spa := common.SliceToIPv4(net.ParseIP("127.0.0.1").To4()) + tpa := common.SliceToIPv4(net.ParseIP("128.9.9.5").To4()) InitARPRequestPacket(pkt, sha, spa, tpa) return pkt } func initEtherAddrs(pkt *Packet) { - pkt.Ether.SAddr = [common.EtherAddrLen]byte{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} - pkt.Ether.DAddr = [common.EtherAddrLen]byte{0x0, 0x11, 0x22, 0x33, 0x44, 0x55} + pkt.Ether.SAddr = common.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} + pkt.Ether.DAddr = common.MACAddress{0x0, 0x11, 0x22, 0x33, 0x44, 0x55} } func initIPv4Addrs(pkt *Packet) { - pkt.GetIPv4().SrcAddr = binary.LittleEndian.Uint32(net.ParseIP("127.0.0.1").To4()) - pkt.GetIPv4().DstAddr = binary.LittleEndian.Uint32(net.ParseIP("128.9.9.5").To4()) + pkt.GetIPv4().SrcAddr = common.SliceToIPv4(net.ParseIP("127.0.0.1").To4()) + pkt.GetIPv4().DstAddr = common.SliceToIPv4(net.ParseIP("128.9.9.5").To4()) } func initIPv6Addrs(pkt *Packet) { diff --git a/packet/vlan_test.go b/packet/vlan_test.go index d1244d28..2d10aedd 100644 --- a/packet/vlan_test.go +++ b/packet/vlan_test.go @@ -5,7 +5,6 @@ package packet import ( - "encoding/binary" "encoding/hex" "net" "reflect" @@ -40,8 +39,8 @@ var ( TimeToLive: uint8(64), NextProtoID: TCPNumber, HdrChecksum: 0, - SrcAddr: binary.LittleEndian.Uint32([]byte(net.ParseIP("131.151.32.21").To4())), - DstAddr: binary.LittleEndian.Uint32([]byte(net.ParseIP("131.151.32.129").To4())), + SrcAddr: SliceToIPv4([]byte(net.ParseIP("131.151.32.21").To4())), + DstAddr: SliceToIPv4([]byte(net.ParseIP("131.151.32.129").To4())), TotalLength: SwapBytesUint16(uint16(IPv4MinLen + TCPMinLen)), } diff --git a/test/performance/perf_gen.go b/test/performance/perf_gen.go index 66889b34..f7f6cf81 100644 --- a/test/performance/perf_gen.go +++ b/test/performance/perf_gen.go @@ -54,8 +54,8 @@ func generatePacket(pkt *packet.Packet, context flow.UserContext) { ipv4 := pkt.GetIPv4() tcp := pkt.GetTCPForIPv4() - ipv4.DstAddr = packet.SwapBytesUint32(uint32(r)) - ipv4.SrcAddr = packet.SwapBytesUint32(uint32(r + 15)) + ipv4.DstAddr = packet.SwapBytesIPv4Addr(IPv4Address(r)) + ipv4.SrcAddr = packet.SwapBytesIPv4Addr(IPv4Address(r + 15)) tcp.DstPort = packet.SwapBytesUint16(r + 25) tcp.SrcPort = packet.SwapBytesUint16(r + 35) diff --git a/test/performance/perf_main.go b/test/performance/perf_main.go index 0098a1ce..13121fea 100644 --- a/test/performance/perf_main.go +++ b/test/performance/perf_main.go @@ -7,6 +7,7 @@ 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" ) @@ -52,10 +53,10 @@ func heavyFunc(currentPacket *packet.Packet, context flow.UserContext) { ipv4 := currentPacket.GetIPv4() if ipv4 != nil { T := ipv4.DstAddr - for j := uint32(0); j < uint32(load); j++ { + for j := common.IPv4Address(0); j < common.IPv4Address(load); j++ { T += j } - for i := uint32(0); i < uint32(loadRW); i++ { + for i := common.IPv4Address(0); i < common.IPv4Address(loadRW); i++ { ipv4.DstAddr = ipv4.SrcAddr + i } ipv4.SrcAddr = 263 + (T) diff --git a/test/performance/perf_seq.go b/test/performance/perf_seq.go index 06714f6c..0940408b 100644 --- a/test/performance/perf_seq.go +++ b/test/performance/perf_seq.go @@ -7,6 +7,7 @@ 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" ) @@ -82,7 +83,7 @@ func heavyFunc(currentPacket *packet.Packet, context flow.UserContext) { if ipv4 != nil { T := (ipv4.DstAddr) for j := uint(0); j < load; j++ { - T += uint32(j) + T += common.IPv4Address(j) } ipv4.SrcAddr = 263 + (T) } diff --git a/test/stability/testCksum/testCksum.go b/test/stability/testCksum/testCksum.go index 0c96702a..66755930 100644 --- a/test/stability/testCksum/testCksum.go +++ b/test/stability/testCksum/testCksum.go @@ -457,16 +457,16 @@ func initPacketCommon(emptyPacket *packet.Packet, length uint16, rnd *rand.Rand) func initPacketIPv4(emptyPacket *packet.Packet) { // Initialize IPv4 addresses emptyPacketIPv4 := emptyPacket.GetIPv4() - emptyPacketIPv4.SrcAddr = packet.SwapBytesUint32((192 << 24) | (168 << 16) | (1 << 8) | 1) - emptyPacketIPv4.DstAddr = packet.SwapBytesUint32((192 << 24) | (168 << 16) | (1 << 8) | 2) + emptyPacketIPv4.SrcAddr = packet.SwapBytesIPv4Addr((192 << 24) | (168 << 16) | (1 << 8) | 1) + emptyPacketIPv4.DstAddr = packet.SwapBytesIPv4Addr((192 << 24) | (168 << 16) | (1 << 8) | 2) emptyPacketIPv4.TimeToLive = 100 } func initPacketIPv6(emptyPacket *packet.Packet) { // Initialize IPv6 addresses emptyPacketIPv6 := emptyPacket.GetIPv6() - emptyPacketIPv6.SrcAddr = [common.IPv6AddrLen]uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - emptyPacketIPv6.DstAddr = [common.IPv6AddrLen]uint8{17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} + emptyPacketIPv6.SrcAddr = common.IPv6Address{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + emptyPacketIPv6.DstAddr = common.IPv6Address{17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} } func initPacketUDP(emptyPacket *packet.Packet) { diff --git a/test/stability/testMerge/testMerge.go b/test/stability/testMerge/testMerge.go index 952cf723..2bd07968 100644 --- a/test/stability/testMerge/testMerge.go +++ b/test/stability/testMerge/testMerge.go @@ -12,6 +12,7 @@ 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/test/stability/stabilityCommon" @@ -63,8 +64,8 @@ var ( // Usually when writing multibyte fields to packet, we should make // sure that byte order in packet buffer is correct and swap bytes if needed. // Here for testing purposes we use addresses with bytes swapped by hand. - ipv4addr1 uint32 = 0x0100007f // 127.0.0.1 - ipv4addr2 uint32 = 0x05090980 // 128.9.9.5 + ipv4addr1 common.IPv4Address = 0x0100007f // 127.0.0.1 + ipv4addr2 common.IPv4Address = 0x05090980 // 128.9.9.5 testDoneEvent *sync.Cond progStart time.Time From 1464b0d8f2f13a2511466f64aaf32978aa8b0ef1 Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Thu, 14 Feb 2019 16:34:45 -0600 Subject: [PATCH 13/24] Moved IP addresses, functions and constants into separate package types --- common/common.go | 405 ------------------ common/error.go | 148 +++++++ common/log.go | 104 +++++ examples/antiddos/antiDDoS.go | 6 +- examples/antiddos/generatorForAntiDDoS.go | 10 +- examples/dpi/main/handlers.go | 6 +- examples/gtpu.go | 18 +- examples/ipsec/ipsec_kernel.go | 30 +- examples/ipsec/stability/stability.go | 6 +- examples/kni.go | 6 +- examples/netlink.go | 17 +- examples/nffPktgen/generator/generator.go | 20 +- examples/nffPktgen/generator/ipv6.go | 6 +- examples/nffPktgen/generator/parseConfig.go | 22 +- examples/pingReplay.go | 4 +- examples/tutorial/common.go | 12 +- examples/tutorial/step10.go | 8 +- examples/tutorial/step11.go | 8 +- examples/tutorial/step9.go | 8 +- flow/flow.go | 11 +- flow/predefined.go | 13 +- low/low.go | 11 +- packet/acl.go | 37 +- packet/acl_internal_test.go | 50 +-- packet/arp.go | 61 +-- packet/arp_test.go | 44 +- packet/checksum.go | 5 +- packet/checksum_test.go | 10 +- packet/gtp.go | 2 +- packet/icmp6.go | 32 +- packet/lpm_test.go | 20 +- packet/mpls.go | 2 +- packet/packet.go | 209 +++++---- packet/packet_test.go | 74 ++-- packet/utils_for_test.go | 20 +- packet/vlan.go | 2 +- packet/vlan_test.go | 52 +-- test/performance/ipsec.go | 16 +- test/performance/latency.go | 4 +- test/performance/perf_gen.go | 8 +- test/performance/perf_main.go | 6 +- test/performance/perf_seq.go | 4 +- test/stability/stabilityCommon/common.go | 21 +- test/stability/testCksum/testCksum.go | 12 +- .../testCksumCommon/testCksumCommon.go | 34 +- test/stability/testMerge/testMerge.go | 6 +- types/Makefile | 15 + types/const.go | 97 +++++ types/ipv4.go | 59 +++ types/ipv6.go | 39 ++ types/mac.go | 16 + 51 files changed, 957 insertions(+), 879 deletions(-) create mode 100644 common/error.go create mode 100644 common/log.go create mode 100644 types/Makefile create mode 100644 types/const.go create mode 100644 types/ipv4.go create mode 100644 types/ipv6.go create mode 100644 types/mac.go diff --git a/common/common.go b/common/common.go index aee3abfa..7c39fcb9 100644 --- a/common/common.go +++ b/common/common.go @@ -7,414 +7,9 @@ package common import ( - "encoding/json" - "fmt" - "io" - "log" - "math" - "net" - "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 ) -type IPv4Address uint32 - -// BytesToIPv4 converts four element address to IPv4Address representation -func BytesToIPv4(a byte, b byte, c byte, d byte) IPv4Address { - return IPv4Address(d)<<24 | IPv4Address(c)<<16 | IPv4Address(b)<<8 | IPv4Address(a) -} - -// ArrayToIPv4 converts four element array to IPv4Address representation -func ArrayToIPv4(a [IPv4AddrLen]byte) IPv4Address { - return IPv4Address(a[3])<<24 | IPv4Address(a[2])<<16 | IPv4Address(a[1])<<8 | IPv4Address(a[0]) -} - -// SliceToIPv4 converts four element slice to IPv4Address representation -func SliceToIPv4(s []byte) IPv4Address { - return IPv4Address(s[3])<<24 | IPv4Address(s[2])<<16 | IPv4Address(s[1])<<8 | IPv4Address(s[0]) -} - -// IPv4ToBytes converts four element address to IPv4Address representation -func IPv4ToBytes(v IPv4Address) [IPv4AddrLen]byte { - return [IPv4AddrLen]uint8{byte(v), byte(v >> 8), byte(v >> 16), byte(v >> 24)} -} - -func (addr IPv4Address) String() string { - return fmt.Sprintf("%d.%d.%d.%d", byte(addr), byte(addr>>8), byte(addr>>16), byte(addr>>24)) -} - -// UnmarshalJSON parses IPv4 address. -func (out *IPv4Address) UnmarshalJSON(b []byte) error { - var s string - if err := json.Unmarshal(b, &s); err != nil { - return err - } - - if ip := net.ParseIP(s); ip != nil { - ipv4 := ip.To4() - if ipv4 == nil { - return fmt.Errorf("Bad IPv4 address %s", s) - } - *out = BytesToIPv4(ipv4[0], ipv4[1], ipv4[2], ipv4[3]) - return nil - } - return fmt.Errorf("Failed to parse address %s", s) -} - -type IPv6Address [IPv6AddrLen]uint8 - -func (addr IPv6Address) String() string { - return fmt.Sprintf("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", - addr[0], addr[1], addr[2], addr[3], - addr[4], addr[5], addr[6], addr[7], - addr[8], addr[9], addr[10], addr[11], - addr[12], addr[13], addr[14], addr[15]) -} - -// UnmarshalJSON parses IPv6 address. -func (out *IPv6Address) UnmarshalJSON(b []byte) error { - var s string - if err := json.Unmarshal(b, &s); err != nil { - return err - } - - if ip := net.ParseIP(s); ip != nil { - ipv6 := ip.To16() - if ipv6 == nil { - return fmt.Errorf("Bad IPv6 address %s", s) - } - copy((*out)[:], ipv6) - return nil - } - return fmt.Errorf("Failed to parse address %s", s) -} - -type MACAddress [EtherAddrLen]uint8 - -// MACToString return MAC address like string -func (mac MACAddress) String() string { - return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) -} - -// 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 - 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) -} - -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) 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/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 66ba8ed5..6db0bcef 100644 --- a/examples/antiddos/generatorForAntiDDoS.go +++ b/examples/antiddos/generatorForAntiDDoS.go @@ -17,9 +17,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" ) const ( @@ -44,7 +44,7 @@ var ( // addresses imitating users sending non flood // flooding user's addresses will be generated - goodAddresses = [goodDataListSize]common.IPv4Address{packet.SwapBytesIPv4Addr(1235), + goodAddresses = [goodDataListSize]types.IPv4Address{packet.SwapBytesIPv4Addr(1235), packet.SwapBytesIPv4Addr(980), packet.SwapBytesIPv4Addr(2405), packet.SwapBytesIPv4Addr(3540)} @@ -116,7 +116,7 @@ func main() { // Function to use in generator func generatePacket(pkt *packet.Packet, context flow.UserContext) { - var address *common.IPv4Address + var address *types.IPv4Address var port *uint16 if pkt == nil { @@ -142,7 +142,7 @@ func generatePacket(pkt *packet.Packet, context flow.UserContext) { *port = goodPorts[indx] atomic.AddUint64(&sentNonFlood, 1) } else { - *address = packet.SwapBytesIPv4Addr(common.IPv4Address(sentPackets)) + *address = packet.SwapBytesIPv4Addr(types.IPv4Address(sentPackets)) *port = packet.SwapBytesUint16(uint16(sentPackets)) } @@ -171,7 +171,7 @@ func checkInputFlow(pkt *packet.Packet, context flow.UserContext) { } } -func isSrcGood(srcAddr common.IPv4Address, 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/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/gtpu.go b/examples/gtpu.go index 094af4dd..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 != common.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 = common.BytesToIPv4(11, 22, 33, 44) - ipv4.DstAddr = common.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 = common.BytesToIPv4(1, 2, 3, 4) - ipv4.DstAddr = common.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 59033701..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 = common.BytesToIPv4(111, 22, 3, 0) - ipv4.DstAddr = common.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 = common.BytesToIPv4(111, 22, 3, 0) - ipv4.DstAddr = common.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/stability/stability.go b/examples/ipsec/stability/stability.go index b45c0dea..32861850 100644 --- a/examples/ipsec/stability/stability.go +++ b/examples/ipsec/stability/stability.go @@ -4,7 +4,7 @@ package main -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" import "github.com/intel-go/nff-go/examples/ipsec" @@ -53,8 +53,8 @@ func gen(pkt *packet.Packet, context flow.UserContext) { pkt.Ether.DAddr = [6]uint8{1, 2, 3, 4, 5, 6} pkt.Ether.SAddr = [6]uint8{1, 2, 3, 4, 5, 6} - ipv4.SrcAddr = common.BytesToIPv4(111, 111, 111, 111) - ipv4.DstAddr = common.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) 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/netlink.go b/examples/netlink.go index 2528f79d..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 []common.IPv4Address +var portToIP []types.IPv4Address // length of portToIp -var lenP2IP common.IPv4Address +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 common.IPv4Address + var next types.IPv4Address if lpm.Lookup(ipv4.DstAddr, &next) { - common.LogDebug(common.Debug, "gateway for packet: ", common.IPv4ToBytes(portToIP[next])) + common.LogDebug(common.Debug, "gateway for packet: ", types.IPv4ToBytes(portToIP[next])) } } } -func netToNffIPv4(netIP net.IP) common.IPv4Address { +func netToNffIPv4(netIP net.IP) types.IPv4Address { if netIP == nil || len(netIP) != 4 { return 0 } - return common.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) (common.IPv4Address, uint8, error) { +func getIPAndDepth(netIP *net.IPNet) (types.IPv4Address, uint8, error) { var ( - ip common.IPv4Address + ip types.IPv4Address depth int ) if netIP != nil { diff --git a/examples/nffPktgen/generator/generator.go b/examples/nffPktgen/generator/generator.go index 8706d89d..809685cd 100644 --- a/examples/nffPktgen/generator/generator.go +++ b/examples/nffPktgen/generator/generator.go @@ -9,8 +9,8 @@ import ( "math/rand" "unsafe" - "github.com/intel-go/nff-go/common" "github.com/intel-go/nff-go/packet" + "github.com/intel-go/nff-go/types" ) func getNextValue(addr *AddrRange) { @@ -127,10 +127,10 @@ func generateARP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) { } l2 := &config.Ether l3 := &l2.ARP - var SHA, THA [common.EtherAddrLen]uint8 - SHA = [common.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)} + 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(common.IPv4Address(l3.SPA.Current)) + SPA := packet.SwapBytesIPv4Addr(types.IPv4Address(l3.SPA.Current)) getNextValue(&l3.SPA) if l3.Operation == packet.ARPRequest { if l3.Gratuitous { @@ -138,7 +138,7 @@ func generateARP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) { panic(fmt.Sprintf("InitGARPAnnouncementRequestPacket returned false")) } } else { - TPA := packet.SwapBytesIPv4Addr(common.IPv4Address(l3.TPA.Current)) + TPA := packet.SwapBytesIPv4Addr(types.IPv4Address(l3.TPA.Current)) getNextValue(&l3.TPA) if !packet.InitARPRequestPacket(pkt, SHA, SPA, TPA) { panic(fmt.Sprintf("InitARPRequestPacket returned false")) @@ -150,9 +150,9 @@ func generateARP(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) { panic(fmt.Sprintf("InitGARPAnnouncementReplyPacket returned false")) } } else { - THA = [common.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)} + 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(common.IPv4Address(l3.TPA.Current)) + 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")) @@ -263,8 +263,8 @@ func fillICMPHdr(pkt *packet.Packet, l4 *ICMPConfig, rnd *rand.Rand) { func fillIPv4Hdr(pkt *packet.Packet, l3 *IPv4Config) { pktIP := (*packet.IPv4Hdr)(pkt.L3) - pktIP.SrcAddr = packet.SwapBytesIPv4Addr(common.IPv4Address(l3.SAddr.Current)) - pktIP.DstAddr = packet.SwapBytesIPv4Addr(common.IPv4Address(l3.DAddr.Current)) + pktIP.SrcAddr = packet.SwapBytesIPv4Addr(types.IPv4Address(l3.SAddr.Current)) + pktIP.DstAddr = packet.SwapBytesIPv4Addr(types.IPv4Address(l3.DAddr.Current)) getNextValue(&l3.DAddr) getNextValue(&l3.SAddr) } @@ -294,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 index abda9a93..1448d1ba 100644 --- a/examples/nffPktgen/generator/ipv6.go +++ b/examples/nffPktgen/generator/ipv6.go @@ -12,8 +12,8 @@ import ( "net" "strings" - "github.com/intel-go/nff-go/common" "github.com/intel-go/nff-go/packet" + "github.com/intel-go/nff-go/types" ) func addAddr(a *[]byte, b []byte) { @@ -133,8 +133,8 @@ func generateICMPIPv6(pkt *packet.Packet, config *PacketConfig, rnd *rand.Rand) func fillIPv6Hdr(pkt *packet.Packet, l3 *IPv6Config) { pktIP := (*packet.IPv6Hdr)(pkt.L3) - copyAddr(pktIP.SrcAddr[:], getNextAddr(&(l3.SAddr)), common.IPv6AddrLen) - copyAddr(pktIP.DstAddr[:], getNextAddr(&(l3.DAddr)), common.IPv6AddrLen) + copyAddr(pktIP.SrcAddr[:], getNextAddr(&(l3.SAddr)), types.IPv6AddrLen) + copyAddr(pktIP.DstAddr[:], getNextAddr(&(l3.DAddr)), types.IPv6AddrLen) } // AddrRange describes range of addresses. diff --git a/examples/nffPktgen/generator/parseConfig.go b/examples/nffPktgen/generator/parseConfig.go index 4c8ae1bf..f80cc154 100644 --- a/examples/nffPktgen/generator/parseConfig.go +++ b/examples/nffPktgen/generator/parseConfig.go @@ -14,7 +14,7 @@ import ( "regexp" "strings" - "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) var mixPattern = regexp.MustCompile(`^mix[0-9]*$`) @@ -108,7 +108,7 @@ type TCPConfig struct { SPort AddrRange DPort AddrRange Seq Sequence - Flags common.TCPFlags + Flags types.TCPFlags DType DataType Bytes RawBytes } @@ -511,26 +511,26 @@ func parseICMPHdr(in map[string]interface{}) (ICMPConfig, error) { 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)) } diff --git a/examples/pingReplay.go b/examples/pingReplay.go index 570d7cfe..edabdff7 100644 --- a/examples/pingReplay.go +++ b/examples/pingReplay.go @@ -2,8 +2,8 @@ package main import ( "flag" - "github.com/intel-go/nff-go/common" "github.com/intel-go/nff-go/flow" + "github.com/intel-go/nff-go/types" ) func main() { @@ -15,7 +15,7 @@ func main() { inputFlow, err := flow.SetReceiver(uint16(*inport)) flow.CheckFatal(err) - flow.CheckFatal(flow.SetIPForPort(uint16(*inport), common.IPv4Address(20)<<24|common.IPv4Address(20)<<16|common.IPv4Address(20)<<8|common.IPv4Address(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 787d1f8d..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 = common.BytesToIPv4(111, 22, 3, 0) - cur.GetIPv4NoCheck().DstAddr = common.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 c980fbed..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 = common.BytesToIPv4(111, 22, 3, 0) - cur.GetIPv4NoCheck().DstAddr = common.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 5e64209c..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 = common.BytesToIPv4(111, 22, 3, 0) - cur.GetIPv4NoCheck().DstAddr = common.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/flow.go b/flow/flow.go index 7f99139b..2e50e019 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -39,11 +39,12 @@ import ( "github.com/intel-go/nff-go/common" "github.com/intel-go/nff-go/low" "github.com/intel-go/nff-go/packet" + "github.com/intel-go/nff-go/types" ) var openFlowsNumber = uint32(0) var createdPorts []port -var portPair map[common.IPv4Address](*port) +var portPair map[types.IPv4Address](*port) var schedState *scheduler var vEach [10][burstSize]uint8 var devices map[string]int @@ -424,7 +425,7 @@ type port struct { willKNI bool // will this port has assigned KNI device KNICoreIndex int port uint16 - MAC common.MACAddress + MAC types.MACAddress InIndex int32 sendRings low.Rings } @@ -586,7 +587,7 @@ func SystemInit(args *Config) error { createdPorts[i].InIndex = maxInIndex } } - portPair = make(map[common.IPv4Address](*port)) + portPair = make(map[types.IPv4Address](*port)) devices = make(map[string]int) // Init scheduler common.LogTitle(common.Initialization, "------------***------ Initializing scheduler -----***------------") @@ -1066,7 +1067,7 @@ func mergeOneFlow(IN *Flow, rings low.Rings) { } // GetPortMACAddress returns default MAC address of an Ethernet port. -func GetPortMACAddress(port uint16) [common.EtherAddrLen]uint8 { +func GetPortMACAddress(port uint16) [types.EtherAddrLen]uint8 { return low.GetPortMACAddress(port) } @@ -1091,7 +1092,7 @@ func GetNameByPort(port uint16) (string, error) { // SetIPForPort sets IP for specified port if it was created. Not thread safe. // Return error if requested port isn't exist or wasn't previously requested. -func SetIPForPort(port uint16, ip common.IPv4Address) error { +func SetIPForPort(port uint16, ip types.IPv4Address) error { for i := range createdPorts { if createdPorts[i].port == port && createdPorts[i].wasRequested { portPair[ip] = &createdPorts[i] diff --git a/flow/predefined.go b/flow/predefined.go index 6cca5f44..621dfd57 100644 --- a/flow/predefined.go +++ b/flow/predefined.go @@ -9,6 +9,7 @@ package flow import ( "github.com/intel-go/nff-go/common" "github.com/intel-go/nff-go/packet" + "github.com/intel-go/nff-go/types" ) func handleARPICMPRequests(current *packet.Packet, context UserContext) bool { @@ -17,11 +18,11 @@ func handleARPICMPRequests(current *packet.Packet, context UserContext) bool { // ARP can be only in IPv4. IPv6 replace it with modified ICMP if arp != nil { if packet.SwapBytesUint16(arp.Operation) != packet.ARPRequest || - arp.THA != [common.EtherAddrLen]byte{} { + arp.THA != [types.EtherAddrLen]byte{} { return false } - port := portPair[common.ArrayToIPv4(arp.TPA)] + port := portPair[types.ArrayToIPv4(arp.TPA)] if port == nil { return false } @@ -31,7 +32,7 @@ func handleARPICMPRequests(current *packet.Packet, context UserContext) bool { if err != nil { common.LogFatal(common.Debug, err) } - packet.InitARPReplyPacket(answerPacket, port.MAC, arp.SHA, common.ArrayToIPv4(arp.TPA), common.ArrayToIPv4(arp.SPA)) + packet.InitARPReplyPacket(answerPacket, port.MAC, arp.SHA, types.ArrayToIPv4(arp.TPA), types.ArrayToIPv4(arp.SPA)) answerPacket.SendPacket(port.port) return false @@ -42,7 +43,7 @@ func handleARPICMPRequests(current *packet.Packet, context UserContext) bool { icmp := current.GetICMPForIPv4() if icmp != nil { // Check that received ICMP packet is echo request packet. - if icmp.Type != common.ICMPTypeEchoRequest || icmp.Code != 0 { + if icmp.Type != types.ICMPTypeEchoRequest || icmp.Code != 0 { return true } @@ -65,9 +66,9 @@ func handleARPICMPRequests(current *packet.Packet, context UserContext) bool { (answerPacket.GetIPv4NoCheck()).DstAddr = ipv4.SrcAddr (answerPacket.GetIPv4NoCheck()).SrcAddr = ipv4.DstAddr answerPacket.ParseL4ForIPv4() - (answerPacket.GetICMPNoCheck()).Type = common.ICMPTypeEchoResponse + (answerPacket.GetICMPNoCheck()).Type = types.ICMPTypeEchoResponse ipv4.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(ipv4)) - answerPacket.ParseL7(common.ICMPNumber) + answerPacket.ParseL7(types.ICMPNumber) icmp.Cksum = packet.SwapBytesUint16(packet.CalculateIPv4ICMPChecksum(ipv4, icmp, answerPacket.Data)) answerPacket.SendPacket(port.port) diff --git a/low/low.go b/low/low.go index 9686dfb5..7df0c381 100644 --- a/low/low.go +++ b/low/low.go @@ -28,6 +28,7 @@ import ( "github.com/intel-go/nff-go/asm" "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) var ringName = 1 @@ -76,8 +77,8 @@ func CheckRSSPacketCount(p *Port, queue int16) int64 { } // GetPortMACAddress gets MAC address of given port. -func GetPortMACAddress(port uint16) [common.EtherAddrLen]uint8 { - var mac [common.EtherAddrLen]uint8 +func GetPortMACAddress(port uint16) [types.EtherAddrLen]uint8 { + var mac [types.EtherAddrLen]uint8 var cmac C.struct_ether_addr C.rte_eth_macaddr_get(C.uint16_t(port), &cmac) @@ -657,7 +658,7 @@ func AllocateMbuf(mb *uintptr, mempool *Mempool) error { // WriteDataToMbuf copies data to mbuf. func WriteDataToMbuf(mb *Mbuf, data []byte) { d := unsafe.Pointer(GetPacketDataStartPointer(mb)) - slice := (*[common.MaxLength]byte)(d)[:len(data)] // copy requires slice + slice := (*[types.MaxLength]byte)(d)[:len(data)] // copy requires slice //TODO need to investigate maybe we need to use C function C.rte_memcpy here copy(slice, data) } @@ -718,12 +719,12 @@ func CreateLPM(name string, socket uint8, maxRules uint32, numberTbl8 uint32, tb } // AddLPMRule adds one rule to LPM table -func AddLPMRule(lpm unsafe.Pointer, ip common.IPv4Address, depth uint8, nextHop common.IPv4Address) int { +func AddLPMRule(lpm unsafe.Pointer, ip types.IPv4Address, depth uint8, nextHop types.IPv4Address) int { return int(C.lpm_add(lpm, C.uint32_t(ip), C.uint8_t(depth), C.uint32_t(nextHop))) } // DeleteLPMRule removes one rule from LPM table -func DeleteLPMRule(lpm unsafe.Pointer, ip common.IPv4Address, depth uint8) int { +func DeleteLPMRule(lpm unsafe.Pointer, ip types.IPv4Address, depth uint8) int { return int(C.lpm_delete(lpm, C.uint32_t(ip), C.uint8_t(depth))) } diff --git a/packet/acl.go b/packet/acl.go index 1593f837..3a01dbca 100644 --- a/packet/acl.go +++ b/packet/acl.go @@ -38,6 +38,7 @@ import ( "strings" "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) type rawL2Rule struct { @@ -207,13 +208,13 @@ func rawL2Parse(rules *rawL2Rules, jp *L2Rules) error { jp.eth[i].ID = 0 jp.eth[i].IDMask = 0 case "ipv4", "Ipv4", "IPv4", "IPV4", "0x0800": - jp.eth[i].ID = common.IPV4Number + jp.eth[i].ID = types.IPV4Number jp.eth[i].IDMask = 0xffff case "ipv6", "Ipv6", "IPv6", "IPV6", "0x86dd": - jp.eth[i].ID = common.IPV6Number + jp.eth[i].ID = types.IPV6Number jp.eth[i].IDMask = 0xffff case "arp", "Arp", "ARP", "0x0806": - jp.eth[i].ID = common.ARPNumber + jp.eth[i].ID = types.ARPNumber jp.eth[i].IDMask = 0xffff default: return common.WrapWithNFError(nil, fmt.Sprintf("Incorrect L3 protocol ID: %v", jup[i].ID), common.IncorrectArgInRules) @@ -241,13 +242,13 @@ func rawL3Parse(rules *rawL3Rules, jp *L3Rules) error { l4temp.ID = 0 l4temp.IDMask = 0 case "tcp", "TCP", "Tcp", "0x06", "6": - l4temp.ID = common.TCPNumber + l4temp.ID = types.TCPNumber l4temp.IDMask = 0xff case "udp", "UDP", "Udp", "0x11", "17": - l4temp.ID = common.UDPNumber + l4temp.ID = types.UDPNumber l4temp.IDMask = 0xff case "icmp", "ICMP", "Icmp", "0x01", "1": - l4temp.ID = common.ICMPNumber + l4temp.ID = types.ICMPNumber l4temp.IDMask = 0xff if jup[i].SrcPort != "ANY" || jup[i].DstPort != "ANY" { return common.WrapWithNFError(nil, "Incorrect request: for ICMP rule Source port and Destination port should be ANY", common.IncorrectArgInRules) @@ -396,8 +397,8 @@ func parseRuleResult(rule string) (uint, error) { } } -func parseAddr4(addr *net.IPNet) (common.IPv4Address, common.IPv4Address) { - return common.IPv4Address(binary.LittleEndian.Uint32(addr.IP)), common.IPv4Address(binary.LittleEndian.Uint32(addr.Mask)) +func parseAddr4(addr *net.IPNet) (types.IPv4Address, types.IPv4Address) { + return types.IPv4Address(binary.LittleEndian.Uint32(addr.IP)), types.IPv4Address(binary.LittleEndian.Uint32(addr.Mask)) } func parseAddr6(addr *net.IPNet) ([16]uint8, [16]uint8) { @@ -413,8 +414,8 @@ type l2Rules struct { OutputNumber uint DAddrNotAny bool SAddrNotAny bool - DAddr common.MACAddress - SAddr common.MACAddress + DAddr types.MACAddress + SAddr types.MACAddress IDMask uint16 ID uint16 } @@ -431,19 +432,19 @@ type l4Rules struct { type l3Rules4 struct { OutputNumber uint - SrcAddr common.IPv4Address - DstAddr common.IPv4Address - SrcMask common.IPv4Address - DstMask common.IPv4Address + SrcAddr types.IPv4Address + DstAddr types.IPv4Address + SrcMask types.IPv4Address + DstMask types.IPv4Address L4 l4Rules } type l3Rules6 struct { OutputNumber uint - SrcAddr common.IPv6Address - DstAddr common.IPv6Address - SrcMask common.IPv6Address - DstMask common.IPv6Address + SrcAddr types.IPv6Address + DstAddr types.IPv6Address + SrcMask types.IPv6Address + DstMask types.IPv6Address L4 l4Rules } diff --git a/packet/acl_internal_test.go b/packet/acl_internal_test.go index dac61b63..86e7d0c8 100644 --- a/packet/acl_internal_test.go +++ b/packet/acl_internal_test.go @@ -60,7 +60,7 @@ import ( "reflect" "testing" - "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) // Data to generate L2 rules @@ -72,12 +72,12 @@ var rulesL2Ctxt = rawL2RuleTestCtxt{ {"", 0}, // case only for ORIG }, srcs: []macAddrTest{ // {rawaddr, ground truth addr info {macaddr, addrNotAny}} - {"ANY", gtMacAddr{common.MACAddress{0, 0, 0, 0, 0, 0}, false}}, + {"ANY", gtMacAddr{types.MACAddress{0, 0, 0, 0, 0, 0}, false}}, {"00:11:22:33:44:55", gtMacAddr{[6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, true}}, }, dsts: []macAddrTest{ // {rawaddr, ground truth addr info {macaddr, addrNotAny}} - {"ANY", gtMacAddr{common.MACAddress{0, 0, 0, 0, 0, 0}, false}}, - {"01:11:21:31:41:51", gtMacAddr{common.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, true}}, + {"ANY", gtMacAddr{types.MACAddress{0, 0, 0, 0, 0, 0}, false}}, + {"01:11:21:31:41:51", gtMacAddr{types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, true}}, }, ids: []idTest{ // {rawid, ground truth {id, idmask}} {"ANY", gtID{0, 0x0000}}, @@ -100,40 +100,40 @@ var rulesL3Ctxt = rawL3RuleTestCtxt{ srcs6: []Addr6Test{ // {rawaddr, ground truth addr info {macaddr, addrNotAny}} {"ANY", gtAddr6{ - common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, {"::/0", gtAddr6{ - common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, {"dead::beef/16", gtAddr6{ - common.IPv6Address{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - common.IPv6Address{0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, }, dsts6: []Addr6Test{ // {rawaddr, ground truth addr info} {"ANY", gtAddr6{ - common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, {"::/0", gtAddr6{ - common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - common.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + types.IPv6Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, }, {"dead::beef/128", gtAddr6{ - common.IPv6Address{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbe, 0xef}, - common.IPv6Address{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + types.IPv6Address{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbe, 0xef}, + types.IPv6Address{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, }, }, }, @@ -1344,13 +1344,13 @@ type Addr6Test struct { } type gtAddr4 struct { - addr common.IPv4Address - mask common.IPv4Address + addr types.IPv4Address + mask types.IPv4Address } type gtAddr6 struct { - addr common.IPv6Address - mask common.IPv6Address + addr types.IPv6Address + mask types.IPv6Address } type portTest struct { @@ -1426,19 +1426,19 @@ type IDMask16 struct { } type Addr4Mask struct { - addr common.IPv4Address - msk common.IPv4Address + addr types.IPv4Address + msk types.IPv4Address ok bool } type Addr6Mask struct { - addr common.IPv6Address - msk common.IPv6Address + addr types.IPv6Address + msk types.IPv6Address ok bool } type MacAddr struct { - addr common.MACAddress + addr types.MACAddress addrNotAny bool ok bool } diff --git a/packet/arp.go b/packet/arp.go index b983ec1d..cc6cfdd5 100644 --- a/packet/arp.go +++ b/packet/arp.go @@ -8,21 +8,22 @@ import ( "fmt" "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) // ARPHdr is protocol structure used in Address Resolution Protocol // for IPv4 to MAC mapping type ARPHdr struct { - HType uint16 // Hardware type, e.g. 1 for Ethernet - PType uint16 // Protocol type, e.g. 0x0800 for IPv4 - HLen uint8 // Hardware address length, e.g. 6 for MAC length - PLen uint8 // Protocol address length, e.g. 4 for IPv4 address length - Operation uint16 // Operation type, see ARP constants - SHA common.MACAddress // Sender hardware address (sender MAC address) - SPA [common.IPv4AddrLen]uint8 // Sender protocol address (sender IPv4 address) + HType uint16 // Hardware type, e.g. 1 for Ethernet + PType uint16 // Protocol type, e.g. 0x0800 for IPv4 + HLen uint8 // Hardware address length, e.g. 6 for MAC length + PLen uint8 // Protocol address length, e.g. 4 for IPv4 address length + Operation uint16 // Operation type, see ARP constants + SHA types.MACAddress // Sender hardware address (sender MAC address) + SPA [types.IPv4AddrLen]uint8 // Sender protocol address (sender IPv4 address) // array is used to avoid alignment (compiler alignes uint32 on 4 bytes) - THA common.MACAddress // Target hardware address (target MAC address) - TPA [common.IPv4AddrLen]uint8 // Target protocol address (target IPv4 address) + THA types.MACAddress // Target hardware address (target MAC address) + TPA [types.IPv4AddrLen]uint8 // Target protocol address (target IPv4 address) // array is used to avoid alignment (compiler alignes uint32 on 4 bytes) } @@ -63,9 +64,9 @@ func initARPCommonData(packet *Packet) bool { arp := packet.GetARPNoCheck() arp.HType = SwapBytesUint16(1) - arp.PType = SwapBytesUint16(common.IPV4Number) - arp.HLen = common.EtherAddrLen - arp.PLen = common.IPv4AddrLen + arp.PType = SwapBytesUint16(types.IPV4Number) + arp.HLen = types.EtherAddrLen + arp.PLen = types.IPv4AddrLen return true } @@ -75,19 +76,19 @@ func initARPCommonData(packet *Packet) bool { // specifies IP address for host which request is sent // for. Destination MAC address in L2 Ethernet header is set to // FF:FF:FF:FF:FF:FF (broadcast) and source address is set to SHA. -func InitARPRequestPacket(packet *Packet, SHA common.MACAddress, SPA, TPA common.IPv4Address) bool { +func InitARPRequestPacket(packet *Packet, SHA types.MACAddress, SPA, TPA types.IPv4Address) bool { if !initARPCommonData(packet) { common.LogWarning(common.Debug, "InitARPRequestPacket: failed to fill common data") return false } packet.Ether.SAddr = SHA - packet.Ether.DAddr = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + packet.Ether.DAddr = types.MACAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} arp := packet.GetARPNoCheck() arp.Operation = SwapBytesUint16(ARPRequest) arp.SHA = SHA - arp.SPA = common.IPv4ToBytes(SPA) - arp.THA = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - arp.TPA = common.IPv4ToBytes(TPA) + arp.SPA = types.IPv4ToBytes(SPA) + arp.THA = types.MACAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + arp.TPA = types.IPv4ToBytes(TPA) return true } @@ -96,7 +97,7 @@ func InitARPRequestPacket(packet *Packet, SHA common.MACAddress, SPA, TPA common // TPA specify target MAC and IP addresses. Destination MAC address // in L2 Ethernet header is set to THA and source address is set to // SHA. -func InitARPReplyPacket(packet *Packet, SHA, THA common.MACAddress, SPA, TPA common.IPv4Address) bool { +func InitARPReplyPacket(packet *Packet, SHA, THA types.MACAddress, SPA, TPA types.IPv4Address) bool { if !initARPCommonData(packet) { common.LogWarning(common.Debug, "InitARPRequestPacket: failed to fill common data") return false @@ -106,9 +107,9 @@ func InitARPReplyPacket(packet *Packet, SHA, THA common.MACAddress, SPA, TPA com arp := packet.GetARPNoCheck() arp.Operation = SwapBytesUint16(ARPReply) arp.SHA = SHA - arp.SPA = common.IPv4ToBytes(SPA) + arp.SPA = types.IPv4ToBytes(SPA) arp.THA = THA - arp.TPA = common.IPv4ToBytes(TPA) + arp.TPA = types.IPv4ToBytes(TPA) return true } @@ -118,19 +119,19 @@ func InitARPReplyPacket(packet *Packet, SHA, THA common.MACAddress, SPA, TPA com // SPA specify sender MAC and IP addresses, TPA is set to the value of // SPA. Destination MAC address in L2 Ethernet header is set to // FF:FF:FF:FF:FF:FF (broadcast) and source address is set to SHA. -func InitGARPAnnouncementRequestPacket(packet *Packet, SHA common.MACAddress, SPA common.IPv4Address) bool { +func InitGARPAnnouncementRequestPacket(packet *Packet, SHA types.MACAddress, SPA types.IPv4Address) bool { if !initARPCommonData(packet) { common.LogWarning(common.Debug, "InitARPRequestPacket: failed to fill common data") return false } packet.Ether.SAddr = SHA - packet.Ether.DAddr = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + packet.Ether.DAddr = types.MACAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} arp := packet.GetARPNoCheck() arp.Operation = SwapBytesUint16(ARPRequest) arp.SHA = SHA - arp.SPA = common.IPv4ToBytes(SPA) - arp.THA = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - arp.TPA = common.IPv4ToBytes(SPA) + arp.SPA = types.IPv4ToBytes(SPA) + arp.THA = types.MACAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + arp.TPA = types.IPv4ToBytes(SPA) return true } @@ -140,18 +141,18 @@ func InitGARPAnnouncementRequestPacket(packet *Packet, SHA common.MACAddress, SP // to zeroes (according to RFC 5227). Destination MAC address in L2 Ethernet header is set // to FF:FF:FF:FF:FF:FF (broadcast) and source address is set // to SHA. -func InitGARPAnnouncementReplyPacket(packet *Packet, SHA common.MACAddress, SPA common.IPv4Address) bool { +func InitGARPAnnouncementReplyPacket(packet *Packet, SHA types.MACAddress, SPA types.IPv4Address) bool { if !initARPCommonData(packet) { common.LogWarning(common.Debug, "InitARPRequestPacket: failed to fill common data") return false } packet.Ether.SAddr = SHA - packet.Ether.DAddr = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + packet.Ether.DAddr = types.MACAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} arp := packet.GetARPNoCheck() arp.Operation = SwapBytesUint16(ARPReply) arp.SHA = SHA - arp.SPA = common.IPv4ToBytes(SPA) - arp.THA = [common.EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - arp.TPA = common.IPv4ToBytes(SPA) + arp.SPA = types.IPv4ToBytes(SPA) + arp.THA = types.MACAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + arp.TPA = types.IPv4ToBytes(SPA) return true } diff --git a/packet/arp_test.go b/packet/arp_test.go index 0936e9b3..88706e0d 100644 --- a/packet/arp_test.go +++ b/packet/arp_test.go @@ -11,7 +11,7 @@ import ( "testing" "unsafe" - . "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) func init() { @@ -32,12 +32,12 @@ func TestInitARPCommonDataPacket(t *testing.T) { pkt := getPacket() initARPCommonData(pkt) - pkt.Ether.DAddr = [6]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - pkt.Ether.SAddr = [6]uint8{0x00, 0x07, 0x0d, 0xaf, 0xf4, 0x54} + pkt.Ether.DAddr = types.MACAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + pkt.Ether.SAddr = types.MACAddress{0x00, 0x07, 0x0d, 0xaf, 0xf4, 0x54} pktARP := pkt.GetARP() pktARP.Operation = SwapBytesUint16(1) - pktARP.SHA = [6]uint8{0x00, 0x07, 0x0d, 0xaf, 0xf4, 0x54} - pktARP.THA = [6]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + pktARP.SHA = types.MACAddress{0x00, 0x07, 0x0d, 0xaf, 0xf4, 0x54} + pktARP.THA = types.MACAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} copy(pktARP.SPA[:], net.ParseIP("24.166.172.1").To4()[:]) copy(pktARP.TPA[:], net.ParseIP("24.166.173.159").To4()[:]) @@ -46,7 +46,7 @@ func TestInitARPCommonDataPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + ARPLen + size := types.EtherLen + types.ARPLen buf := (*[1 << 30]byte)(unsafe.Pointer(pkt.StartAtOffset(0)))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -56,11 +56,11 @@ func TestInitARPCommonDataPacket(t *testing.T) { func TestInitARPRequestPacket(t *testing.T) { // Create empty packet, set UDP header fields pkt := getPacket() - sha := [6]uint8{0x00, 0x07, 0x0d, 0xaf, 0xf4, 0x54} + sha := types.MACAddress{0x00, 0x07, 0x0d, 0xaf, 0xf4, 0x54} srcIP := net.ParseIP("24.166.172.1").To4() dstIP := net.ParseIP("24.166.173.159").To4() - spa := BytesToIPv4(srcIP[0], srcIP[1], srcIP[2], srcIP[3]) - tpa := BytesToIPv4(dstIP[0], dstIP[1], dstIP[2], dstIP[3]) + spa := types.BytesToIPv4(srcIP[0], srcIP[1], srcIP[2], srcIP[3]) + tpa := types.BytesToIPv4(dstIP[0], dstIP[1], dstIP[2], dstIP[3]) InitARPRequestPacket(pkt, sha, spa, tpa) // Create ground truth packet @@ -68,7 +68,7 @@ func TestInitARPRequestPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + ARPLen + size := types.EtherLen + types.ARPLen buf := (*[1 << 30]byte)(unsafe.Pointer(pkt.StartAtOffset(0)))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -78,12 +78,12 @@ func TestInitARPRequestPacket(t *testing.T) { func TestInitARPReplyPacket(t *testing.T) { // Create empty packet, set UDP header fields pkt := getPacket() - tha := [6]uint8{0xc4, 0x01, 0x32, 0x58, 0x00, 0x00} - sha := [6]uint8{0xc4, 0x02, 0x32, 0x6b, 0x00, 0x00} + tha := types.MACAddress{0xc4, 0x01, 0x32, 0x58, 0x00, 0x00} + sha := types.MACAddress{0xc4, 0x02, 0x32, 0x6b, 0x00, 0x00} srcIP := net.ParseIP("10.0.0.2").To4() dstIP := net.ParseIP("10.0.0.1").To4() - spa := BytesToIPv4(srcIP[0], srcIP[1], srcIP[2], srcIP[3]) - tpa := BytesToIPv4(dstIP[0], dstIP[1], dstIP[2], dstIP[3]) + spa := types.BytesToIPv4(srcIP[0], srcIP[1], srcIP[2], srcIP[3]) + tpa := types.BytesToIPv4(dstIP[0], dstIP[1], dstIP[2], dstIP[3]) InitARPReplyPacket(pkt, sha, tha, spa, tpa) // Create ground truth packet @@ -91,7 +91,7 @@ func TestInitARPReplyPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + ARPLen + size := types.EtherLen + types.ARPLen buf := (*[1 << 30]byte)(unsafe.Pointer(pkt.StartAtOffset(0)))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -101,9 +101,9 @@ func TestInitARPReplyPacket(t *testing.T) { func TestInitGARPAnnouncementRequestPacket(t *testing.T) { // Create empty packet, set UDP header fields pkt := getPacket() - sha := [6]uint8{0x02, 0x02, 0x02, 0x02, 0x02, 0x02} + sha := types.MACAddress{0x02, 0x02, 0x02, 0x02, 0x02, 0x02} srcIP := net.ParseIP("192.168.1.1").To4() - spa := BytesToIPv4(srcIP[0], srcIP[1], srcIP[2], srcIP[3]) + spa := types.BytesToIPv4(srcIP[0], srcIP[1], srcIP[2], srcIP[3]) InitGARPAnnouncementRequestPacket(pkt, sha, spa) @@ -112,7 +112,7 @@ func TestInitGARPAnnouncementRequestPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + ARPLen + size := types.EtherLen + types.ARPLen buf := (*[1 << 30]byte)(unsafe.Pointer(pkt.StartAtOffset(0)))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -122,9 +122,9 @@ func TestInitGARPAnnouncementRequestPacket(t *testing.T) { func TestInitGARPAnnouncementReplyPacket(t *testing.T) { // Create empty packet, set UDP header fields pkt := getPacket() - sha := [6]uint8{0x00, 0x00, 0x0c, 0x07, 0xac, 0x01} + sha := types.MACAddress{0x00, 0x00, 0x0c, 0x07, 0xac, 0x01} srcIP := net.ParseIP("10.0.0.6").To4() - spa := BytesToIPv4(srcIP[0], srcIP[1], srcIP[2], srcIP[3]) + spa := types.BytesToIPv4(srcIP[0], srcIP[1], srcIP[2], srcIP[3]) InitGARPAnnouncementReplyPacket(pkt, sha, spa) @@ -133,7 +133,7 @@ func TestInitGARPAnnouncementReplyPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + ARPLen + size := types.EtherLen + types.ARPLen buf := (*[1 << 30]byte)(unsafe.Pointer(pkt.StartAtOffset(0)))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -149,7 +149,7 @@ func TestInitEmptyARPPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + ARPLen + size := types.EtherLen + types.ARPLen buf := (*[1 << 30]byte)(unsafe.Pointer(pkt.StartAtOffset(0)))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) diff --git a/packet/checksum.go b/packet/checksum.go index b1ec78c3..a6c88814 100644 --- a/packet/checksum.go +++ b/packet/checksum.go @@ -5,9 +5,10 @@ package packet import ( - . "github.com/intel-go/nff-go/common" - "github.com/intel-go/nff-go/low" "unsafe" + + "github.com/intel-go/nff-go/low" + . "github.com/intel-go/nff-go/types" ) // Setting up flags for hardware offloading for hardware calculation of checksums diff --git a/packet/checksum_test.go b/packet/checksum_test.go index ed778093..062f2fec 100644 --- a/packet/checksum_test.go +++ b/packet/checksum_test.go @@ -5,7 +5,7 @@ package packet import ( - "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" "net" "testing" ) @@ -158,15 +158,15 @@ func TestCalculateIPv6ICMPChecksum(t *testing.T) { func initIPv4AddrsLocal(pkt *Packet) { ipv4 := pkt.GetIPv4() - ipv4.SrcAddr = common.SliceToIPv4(net.ParseIP("131.151.32.21").To4()) - ipv4.DstAddr = common.SliceToIPv4(net.ParseIP("131.151.32.129").To4()) + ipv4.SrcAddr = types.SliceToIPv4(net.ParseIP("131.151.32.21").To4()) + ipv4.DstAddr = types.SliceToIPv4(net.ParseIP("131.151.32.129").To4()) ipv4.HdrChecksum = 0 } func initIPv6AddrsLocal(pkt *Packet) { ipv6 := pkt.GetIPv6() - copy(ipv6.SrcAddr[:], net.ParseIP("2001:db8:0:0:1::1")[:common.IPv6AddrLen]) - copy(ipv6.DstAddr[:], net.ParseIP("2001:db8:0:0:1::12")[:common.IPv6AddrLen]) + copy(ipv6.SrcAddr[:], net.ParseIP("2001:db8:0:0:1::1")[:types.IPv6AddrLen]) + copy(ipv6.DstAddr[:], net.ParseIP("2001:db8:0:0:1::12")[:types.IPv6AddrLen]) } func initData(pkt *Packet) { diff --git a/packet/gtp.go b/packet/gtp.go index fca67365..ae52fbe2 100644 --- a/packet/gtp.go +++ b/packet/gtp.go @@ -13,7 +13,7 @@ import ( "fmt" "unsafe" - . "github.com/intel-go/nff-go/common" + . "github.com/intel-go/nff-go/types" ) // GTPv1-U and GTPv1-C diff --git a/packet/icmp6.go b/packet/icmp6.go index 24eca73c..dd7ff476 100644 --- a/packet/icmp6.go +++ b/packet/icmp6.go @@ -7,7 +7,7 @@ package packet import ( "unsafe" - "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) const ( @@ -38,13 +38,13 @@ var ( type ICMPv6NDSourceLinkLayerAddressOption struct { Type uint8 Length uint8 - LinkLayerAddress common.MACAddress + LinkLayerAddress types.MACAddress } type ICMPv6NDTargetLinkLayerAddressOption struct { Type uint8 Length uint8 - LinkLayerAddress common.MACAddress + LinkLayerAddress types.MACAddress } type ICMPv6NDPrefixInformationOption struct { @@ -55,7 +55,7 @@ type ICMPv6NDPrefixInformationOption struct { ValidLifetime uint32 PreferredLifetime uint32 Reserved2 uint32 - Prefix common.IPv6Address + Prefix types.IPv6Address } type ICMPv6NDRedirectedHeaderOption struct { @@ -71,11 +71,11 @@ type ICMPv6NDMTUOption struct { } type ICMPv6NeighborSolicitationMessage struct { - TargetAddr common.IPv6Address + TargetAddr types.IPv6Address } type ICMPv6NeighborAdvertisementMessage struct { - TargetAddr common.IPv6Address + TargetAddr types.IPv6Address } // GetICMPv6NeighborSolicitationMessage returns pointer to ICMPv6 @@ -126,7 +126,7 @@ func (packet *Packet) GetICMPv6NDTargetLinkLayerAddressOption(msgLength uint) *I // CalculateIPv6LinkLocalAddrForMAC generates IPv6 link local address // based on interface MAC address. -func CalculateIPv6LinkLocalAddrForMAC(llAddr *common.IPv6Address, mac common.MACAddress) { +func CalculateIPv6LinkLocalAddrForMAC(llAddr *types.IPv6Address, mac types.MACAddress) { copy((*llAddr)[:], ipv6LinkLocalPrefix) (*llAddr)[8] = mac[0] ^ 0x02 (*llAddr)[9] = mac[1] @@ -142,14 +142,14 @@ func CalculateIPv6LinkLocalAddrForMAC(llAddr *common.IPv6Address, mac common.MAC // that other hosts use to solicit its MAC address. This address is // used as destination for all Neighbor Solicitation ICMPv6 messages // and NAT should answer packets coming to it. -func CalculateIPv6MulticastAddrForDstIP(muticastAddr *common.IPv6Address, dstIP common.IPv6Address) { +func CalculateIPv6MulticastAddrForDstIP(muticastAddr *types.IPv6Address, dstIP types.IPv6Address) { copy((*muticastAddr)[:], ipv6LinkLocalMulticastPrefix) (*muticastAddr)[13] = dstIP[13] (*muticastAddr)[14] = dstIP[14] (*muticastAddr)[15] = dstIP[15] } -func CalculateIPv6BroadcastMACForDstMulticastIP(dstMAC *common.MACAddress, dstIP common.IPv6Address) { +func CalculateIPv6BroadcastMACForDstMulticastIP(dstMAC *types.MACAddress, dstIP types.IPv6Address) { copy((*dstMAC)[:], ipv6EtherMulticastPrefix) (*dstMAC)[2] = dstIP[12] (*dstMAC)[3] = dstIP[13] @@ -160,10 +160,10 @@ func CalculateIPv6BroadcastMACForDstMulticastIP(dstMAC *common.MACAddress, dstIP // InitICMPv6NeighborSolicitationPacket allocates and initializes // ICMPv6 Neighbor Solicitation request message packet with source MAC // and IPv6 address and target IPv6 address. -func InitICMPv6NeighborSolicitationPacket(packet *Packet, srcMAC common.MACAddress, srcIP, dstIP common.IPv6Address) { +func InitICMPv6NeighborSolicitationPacket(packet *Packet, srcMAC types.MACAddress, srcIP, dstIP types.IPv6Address) { InitEmptyIPv6ICMPPacket(packet, ICMPv6NeighborSolicitationMessageSize+ICMPv6NDSourceLinkLayerAddressOptionSize) - var targetMulticastAddr common.IPv6Address + var targetMulticastAddr types.IPv6Address CalculateIPv6MulticastAddrForDstIP(&targetMulticastAddr, dstIP) // Fill up L2 @@ -177,12 +177,12 @@ func InitICMPv6NeighborSolicitationPacket(packet *Packet, srcMAC common.MACAddre // Fill up L4 icmp := packet.GetICMPNoCheck() - icmp.Type = common.ICMPv6NeighborSolicitation + icmp.Type = types.ICMPv6NeighborSolicitation icmp.Identifier = 0 icmp.SeqNum = 0 // Fill up L7 - packet.ParseL7(common.ICMPv6Number) + packet.ParseL7(types.ICMPv6Number) msg := packet.GetICMPv6NeighborSolicitationMessage() msg.TargetAddr = dstIP option := packet.GetICMPv6NDSourceLinkLayerAddressOption(ICMPv6NeighborSolicitationMessageSize) @@ -194,7 +194,7 @@ func InitICMPv6NeighborSolicitationPacket(packet *Packet, srcMAC common.MACAddre // InitICMPv6NeighborAdvertisementPacket allocates and initializes // ICMPv6 Neighbor Advertisement answer message packet with source MAC // and IPv6 address and target IPv6 address. -func InitICMPv6NeighborAdvertisementPacket(packet *Packet, srcMAC, dstMAC common.MACAddress, srcIP, dstIP common.IPv6Address) { +func InitICMPv6NeighborAdvertisementPacket(packet *Packet, srcMAC, dstMAC types.MACAddress, srcIP, dstIP types.IPv6Address) { InitEmptyIPv6ICMPPacket(packet, ICMPv6NeighborAdvertisementMessageSize+ICMPv6NDTargetLinkLayerAddressOptionSize) // Fill up L2 @@ -208,12 +208,12 @@ func InitICMPv6NeighborAdvertisementPacket(packet *Packet, srcMAC, dstMAC common // Fill up L4 icmp := packet.GetICMPNoCheck() - icmp.Type = common.ICMPv6NeighborAdvertisement + icmp.Type = types.ICMPv6NeighborAdvertisement icmp.Identifier = SwapBytesUint16(ICMPv6NDSolicitedFlag | ICMPv6NDOverrideFlag) icmp.SeqNum = 0 // Fill up L7 - packet.ParseL7(common.ICMPv6Number) + packet.ParseL7(types.ICMPv6Number) msg := packet.GetICMPv6NeighborAdvertisementMessage() msg.TargetAddr = srcIP option := packet.GetICMPv6NDTargetLinkLayerAddressOption(ICMPv6NeighborAdvertisementMessageSize) diff --git a/packet/lpm_test.go b/packet/lpm_test.go index 7f99565c..5ad3dfdf 100644 --- a/packet/lpm_test.go +++ b/packet/lpm_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) func init() { @@ -18,8 +18,8 @@ func init() { rand.Seed(time.Now().UTC().UnixNano()) } -var zero common.IPv4Address = 0 -var next common.IPv4Address +var zero types.IPv4Address = 0 +var next types.IPv4Address var stepM = 1000 var stepN = 10 @@ -30,13 +30,13 @@ func TestOneRule(t *testing.T) { for i := 0; i < stepM; i++ { ip_number := 1 + rand.Intn(32) mask_len := uint8(1 + rand.Intn(32)) - next_hop := common.IPv4Address(rand.Intn(100)) + next_hop := types.IPv4Address(rand.Intn(100)) // Construct ip ip := constructIP(ip_number) // Construct mask mask := zero - for u := zero; u < common.IPv4Address(mask_len); u++ { + for u := zero; u < types.IPv4Address(mask_len); u++ { mask = mask | (1 << (31 - u)) } @@ -134,8 +134,8 @@ func TestMultipleRules(t *testing.T) { lpm.Free() } -func constructIP(ip_number int) common.IPv4Address { - var ip common.IPv4Address +func constructIP(ip_number int) types.IPv4Address { + var ip types.IPv4Address if ip_number < 16 { ip = zero for j := 0; j < ip_number; j++ { @@ -158,15 +158,15 @@ func constructIP(ip_number int) common.IPv4Address { return ip } -func testIP(ip common.IPv4Address, mask_len uint8) (int, int, []common.IPv4Address, []common.IPv4Address) { +func testIP(ip types.IPv4Address, mask_len uint8) (int, int, []types.IPv4Address, []types.IPv4Address) { right := int(math.Pow(2, float64(32-mask_len))) wrong := int(math.Pow(2, float64(mask_len)) - 1) rightN := rand.Intn(right)%stepK + 1 wrongN := rand.Intn(wrong)%stepK + 1 - rightIP := make([]common.IPv4Address, rightN, rightN) - wrongIP := make([]common.IPv4Address, wrongN, wrongN) + rightIP := make([]types.IPv4Address, rightN, rightN) + wrongIP := make([]types.IPv4Address, wrongN, wrongN) rightIP[0] = ip for i := 1; i < rightN; i++ { diff --git a/packet/mpls.go b/packet/mpls.go index 2202b499..3c0518d7 100644 --- a/packet/mpls.go +++ b/packet/mpls.go @@ -8,7 +8,7 @@ import ( "fmt" "unsafe" - . "github.com/intel-go/nff-go/common" + . "github.com/intel-go/nff-go/types" ) type MPLSHdr struct { diff --git a/packet/packet.go b/packet/packet.go index 512d1f03..5576486a 100644 --- a/packet/packet.go +++ b/packet/packet.go @@ -47,6 +47,7 @@ import ( . "github.com/intel-go/nff-go/common" "github.com/intel-go/nff-go/low" + "github.com/intel-go/nff-go/types" ) var mbufStructSize uintptr @@ -69,9 +70,9 @@ func init() { // EtherHdr L2 header from DPDK: lib/librte_ether/rte_ehter.h type EtherHdr struct { - DAddr MACAddress // Destination address - SAddr MACAddress // Source address - EtherType uint16 // Frame type + DAddr types.MACAddress // Destination address + SAddr types.MACAddress // Source address + EtherType uint16 // Frame type } func (hdr *EtherHdr) String() string { @@ -86,11 +87,11 @@ Ethernet Destination: %s var ( etherTypeNameLookupTable = map[uint16]string{ - SwapIPV4Number: "IPv4", - SwapARPNumber: "ARP", - SwapVLANNumber: "VLAN", - SwapMPLSNumber: "MPLS", - SwapIPV6Number: "IPv6", + types.SwapIPV4Number: "IPv4", + types.SwapARPNumber: "ARP", + types.SwapVLANNumber: "VLAN", + types.SwapMPLSNumber: "MPLS", + types.SwapIPV6Number: "IPv6", } ) @@ -104,20 +105,16 @@ func getEtherTypeName(et uint16) string { // IPv4Hdr L3 header from DPDK: lib/librte_net/rte_ip.h type IPv4Hdr struct { - VersionIhl uint8 // version and header length - TypeOfService uint8 // type of service - TotalLength uint16 // length of packet - PacketID uint16 // packet ID - FragmentOffset uint16 // fragmentation offset - TimeToLive uint8 // time to live - NextProtoID uint8 // protocol ID - HdrChecksum uint16 // header checksum - SrcAddr IPv4Address // source address - DstAddr IPv4Address // destination address -} - -func IPv4ArrayToString(addr [IPv4AddrLen]uint8) string { - return fmt.Sprintf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]) + VersionIhl uint8 // version and header length + TypeOfService uint8 // type of service + TotalLength uint16 // length of packet + PacketID uint16 // packet ID + FragmentOffset uint16 // fragmentation offset + TimeToLive uint8 // time to live + NextProtoID uint8 // protocol ID + HdrChecksum uint16 // header checksum + SrcAddr types.IPv4Address // source address + DstAddr types.IPv4Address // destination address } func (hdr *IPv4Hdr) String() string { @@ -129,12 +126,12 @@ func (hdr *IPv4Hdr) String() string { // IPv6Hdr L3 header from DPDK: lib/librte_net/rte_ip.h type IPv6Hdr struct { - VtcFlow uint32 // IP version, traffic class & flow label - PayloadLen uint16 // IP packet length - includes sizeof(ip_header) - Proto uint8 // Protocol, next header - HopLimits uint8 // Hop limits - SrcAddr IPv6Address // IP address of source host - DstAddr IPv6Address // IP address of destination host(s) + VtcFlow uint32 // IP version, traffic class & flow label + PayloadLen uint16 // IP packet length - includes sizeof(ip_header) + Proto uint8 // Protocol, next header + HopLimits uint8 // Hop limits + SrcAddr types.IPv6Address // IP address of source host + DstAddr types.IPv6Address // IP address of destination host(s) } func (hdr *IPv6Hdr) String() string { @@ -146,15 +143,15 @@ func (hdr *IPv6Hdr) String() string { // TCPHdr L4 header from DPDK: lib/librte_net/rte_tcp.h type TCPHdr struct { - SrcPort uint16 // TCP source port - DstPort uint16 // TCP destination port - SentSeq uint32 // TX data sequence number - RecvAck uint32 // RX data acknowledgement sequence number - DataOff uint8 // Data offset - TCPFlags TCPFlags // TCP flags - RxWin uint16 // RX flow control window - Cksum uint16 // TCP checksum - TCPUrp uint16 // TCP urgent pointer, if any + SrcPort uint16 // TCP source port + DstPort uint16 // TCP destination port + SentSeq uint32 // TX data sequence number + RecvAck uint32 // RX data acknowledgement sequence number + DataOff uint8 // Data offset + TCPFlags types.TCPFlags // TCP flags + RxWin uint16 // RX flow control window + Cksum uint16 // TCP checksum + TCPUrp uint16 // TCP urgent pointer, if any } func (hdr *TCPHdr) String() string { @@ -222,7 +219,7 @@ type Packet struct { func (packet *Packet) unparsed() unsafe.Pointer { ether := unsafe.Pointer(packet.Ether) - return unsafe.Pointer(uintptr(ether) + EtherLen) + return unsafe.Pointer(uintptr(ether) + types.EtherLen) } // StartAtOffset function return pointer to first byte of packet @@ -239,7 +236,7 @@ func (packet *Packet) ParseL3() { // GetIPv4 ensures if EtherType is IPv4 and casts L3 pointer to IPv4Hdr type. func (packet *Packet) GetIPv4() *IPv4Hdr { - if packet.Ether.EtherType == SwapBytesUint16(IPV4Number) { + if packet.Ether.EtherType == SwapBytesUint16(types.IPV4Number) { return (*IPv4Hdr)(packet.L3) } return nil @@ -252,7 +249,7 @@ func (packet *Packet) GetIPv4NoCheck() *IPv4Hdr { // GetARP ensures if EtherType is ARP and casts L3 pointer to ARPHdr type. func (packet *Packet) GetARP() *ARPHdr { - if packet.Ether.EtherType == SwapBytesUint16(ARPNumber) { + if packet.Ether.EtherType == SwapBytesUint16(types.ARPNumber) { return (*ARPHdr)(packet.L3) } return nil @@ -265,7 +262,7 @@ func (packet *Packet) GetARPNoCheck() *ARPHdr { // GetIPv6 ensures if EtherType is IPv6 and cast L3 pointer to IPv6Hdr type. func (packet *Packet) GetIPv6() *IPv6Hdr { - if packet.Ether.EtherType == SwapBytesUint16(IPV6Number) { + if packet.Ether.EtherType == SwapBytesUint16(types.IPV6Number) { return (*IPv6Hdr)(packet.L3) } return nil @@ -284,12 +281,12 @@ func (packet *Packet) ParseL4ForIPv4() { // ParseL4ForIPv6 set L4 to start of L4 header, if L3 protocol is IPv6. func (packet *Packet) ParseL4ForIPv6() { - packet.L4 = unsafe.Pointer(uintptr(packet.L3) + uintptr(IPv6Len)) + packet.L4 = unsafe.Pointer(uintptr(packet.L3) + uintptr(types.IPv6Len)) } // GetTCPForIPv4 ensures if L4 type is TCP and cast L4 pointer to TCPHdr type. func (packet *Packet) GetTCPForIPv4() *TCPHdr { - if packet.GetIPv4NoCheck().NextProtoID == TCPNumber { + if packet.GetIPv4NoCheck().NextProtoID == types.TCPNumber { return (*TCPHdr)(packet.L4) } return nil @@ -302,7 +299,7 @@ func (packet *Packet) GetTCPNoCheck() *TCPHdr { // GetTCPForIPv6 ensures if L4 type is TCP and cast L4 pointer to *TCPHdr type. func (packet *Packet) GetTCPForIPv6() *TCPHdr { - if packet.GetIPv6NoCheck().Proto == TCPNumber { + if packet.GetIPv6NoCheck().Proto == types.TCPNumber { return (*TCPHdr)(packet.L4) } return nil @@ -310,7 +307,7 @@ func (packet *Packet) GetTCPForIPv6() *TCPHdr { // GetUDPForIPv4 ensures if L4 type is UDP and cast L4 pointer to *UDPHdr type. func (packet *Packet) GetUDPForIPv4() *UDPHdr { - if packet.GetIPv4NoCheck().NextProtoID == UDPNumber { + if packet.GetIPv4NoCheck().NextProtoID == types.UDPNumber { return (*UDPHdr)(packet.L4) } return nil @@ -323,7 +320,7 @@ func (packet *Packet) GetUDPNoCheck() *UDPHdr { // GetUDPForIPv6 ensures if L4 type is UDP and cast L4 pointer to *UDPHdr type. func (packet *Packet) GetUDPForIPv6() *UDPHdr { - if packet.GetIPv6NoCheck().Proto == UDPNumber { + if packet.GetIPv6NoCheck().Proto == types.UDPNumber { return (*UDPHdr)(packet.L4) } return nil @@ -332,7 +329,7 @@ func (packet *Packet) GetUDPForIPv6() *UDPHdr { // GetICMPForIPv4 ensures if L4 type is ICMP and cast L4 pointer to *ICMPHdr type. // L3 supposed to be parsed before and of IPv4 type. func (packet *Packet) GetICMPForIPv4() *ICMPHdr { - if packet.GetIPv4NoCheck().NextProtoID == ICMPNumber { + if packet.GetIPv4NoCheck().NextProtoID == types.ICMPNumber { return (*ICMPHdr)(packet.L4) } return nil @@ -346,7 +343,7 @@ func (packet *Packet) GetICMPNoCheck() *ICMPHdr { // GetICMPForIPv6 ensures if L4 type is ICMP and cast L4 pointer to *ICMPHdr type. // L3 supposed to be parsed before and of IPv6 type. func (packet *Packet) GetICMPForIPv6() *ICMPHdr { - if packet.GetIPv6NoCheck().Proto == ICMPv6Number { + if packet.GetIPv6NoCheck().Proto == types.ICMPv6Number { return (*ICMPHdr)(packet.L4) } return nil @@ -394,14 +391,14 @@ func (packet *Packet) ParseAllKnownL4ForIPv6() (*TCPHdr, *UDPHdr, *ICMPHdr) { // ParseL7 fills pointers to all supported headers and data field. func (packet *Packet) ParseL7(protocol uint) { switch protocol { - case TCPNumber: + case types.TCPNumber: packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(((*TCPHdr)(packet.L4)).DataOff&0xf0)>>2) - case UDPNumber: - packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(UDPLen)) - case ICMPNumber: + case types.UDPNumber: + packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(types.UDPLen)) + case types.ICMPNumber: fallthrough - case ICMPv6Number: - packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(ICMPLen)) + case types.ICMPv6Number: + packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(types.ICMPLen)) } } @@ -423,9 +420,9 @@ func (packet *Packet) ParseData() int { if pktTCP != nil { packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(((*TCPHdr)(packet.L4)).DataOff&0xf0)>>2) } else if pktUDP != nil { - packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(UDPLen)) + packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(types.UDPLen)) } else if pktICMP != nil { - packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(ICMPLen)) + packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(types.ICMPLen)) } else { return -1 } @@ -482,7 +479,7 @@ func GeneratePacketFromByte(packet *Packet, data []byte) bool { // InitEmptyPacket initializes input packet with preallocated plSize of bytes for payload // and init pointer to Ethernet header. func InitEmptyPacket(packet *Packet, plSize uint) bool { - bufSize := plSize + EtherLen + bufSize := plSize + types.EtherLen if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyPacket: Cannot append mbuf") return false @@ -492,7 +489,7 @@ func InitEmptyPacket(packet *Packet, plSize uint) bool { } func fillIPv4Default(packet *Packet, plLen uint16, nextProto uint8) { - packet.GetIPv4NoCheck().VersionIhl = IPv4VersionIhl + packet.GetIPv4NoCheck().VersionIhl = types.IPv4VersionIhl packet.GetIPv4NoCheck().TotalLength = SwapBytesUint16(plLen) packet.GetIPv4NoCheck().NextProtoID = nextProto packet.GetIPv4NoCheck().TimeToLive = 64 @@ -500,7 +497,7 @@ func fillIPv4Default(packet *Packet, plLen uint16, nextProto uint8) { func fillIPv6Default(packet *Packet, totalLen uint16, nextProto uint8) { packet.GetIPv6NoCheck().PayloadLen = SwapBytesUint16(totalLen) - packet.GetIPv6NoCheck().VtcFlow = IPv6VtcFlow + packet.GetIPv6NoCheck().VtcFlow = types.IPv6VtcFlow packet.GetIPv6NoCheck().Proto = nextProto packet.GetIPv6NoCheck().HopLimits = 255 } @@ -510,20 +507,20 @@ func fillIPv6Default(packet *Packet, totalLen uint16, nextProto uint8) { func InitEmptyIPv4Packet(packet *Packet, plSize uint) bool { // TODO After mandatory fields, IPv4 header optionally may have options of variable length // Now pre-allocate space only for mandatory fields - bufSize := plSize + EtherLen + IPv4MinLen + bufSize := plSize + types.EtherLen + types.IPv4MinLen if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyIPv4Packet: Cannot append mbuf") return false } - packet.Ether.EtherType = SwapBytesUint16(IPV4Number) - packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + IPv4MinLen) + packet.Ether.EtherType = SwapBytesUint16(types.IPV4Number) + packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + types.IPv4MinLen) packet.ParseL3() - fillIPv4Default(packet, uint16(IPv4MinLen+plSize), NoNextHeader) + fillIPv4Default(packet, uint16(types.IPv4MinLen+plSize), types.NoNextHeader) if hwtxchecksum { packet.GetIPv4NoCheck().HdrChecksum = 0 - low.SetTXIPv4OLFlags(packet.CMbuf, EtherLen, IPv4MinLen) + low.SetTXIPv4OLFlags(packet.CMbuf, types.EtherLen, types.IPv4MinLen) } return true } @@ -531,28 +528,28 @@ func InitEmptyIPv4Packet(packet *Packet, plSize uint) bool { // InitEmptyIPv6Packet initializes input packet with preallocated plSize of bytes for payload // and init pointers to Ethernet and IPv6 headers. func InitEmptyIPv6Packet(packet *Packet, plSize uint) bool { - bufSize := plSize + EtherLen + IPv6Len + bufSize := plSize + types.EtherLen + types.IPv6Len if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyIPv6Packet: Cannot append mbuf") return false } - packet.Ether.EtherType = SwapBytesUint16(IPV6Number) - packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + IPv6Len) + packet.Ether.EtherType = SwapBytesUint16(types.IPV6Number) + packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + types.IPv6Len) packet.ParseL3() - fillIPv6Default(packet, uint16(plSize), NoNextHeader) + fillIPv6Default(packet, uint16(plSize), types.NoNextHeader) return true } // InitEmptyARPPacket initializes empty ARP packet func InitEmptyARPPacket(packet *Packet) bool { - var bufSize uint = EtherLen + ARPLen + var bufSize uint = types.EtherLen + types.ARPLen if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyARPPacket: Cannot append mbuf") return false } - packet.Ether.EtherType = SwapBytesUint16(ARPNumber) + packet.Ether.EtherType = SwapBytesUint16(types.ARPNumber) packet.ParseL3() return true } @@ -564,22 +561,22 @@ func InitEmptyARPPacket(packet *Packet) bool { func InitEmptyIPv4TCPPacket(packet *Packet, plSize uint) bool { // Now user cannot set explicitly optional fields, so len of header is supposed to be equal to TCPMinLen // TODO support variable header length (ask header length from user) - bufSize := plSize + EtherLen + IPv4MinLen + TCPMinLen + bufSize := plSize + types.EtherLen + types.IPv4MinLen + types.TCPMinLen if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyPacket: Cannot append mbuf") return false } - packet.Ether.EtherType = SwapBytesUint16(IPV4Number) + packet.Ether.EtherType = SwapBytesUint16(types.IPV4Number) packet.ParseL3() - fillIPv4Default(packet, uint16(IPv4MinLen+TCPMinLen+plSize), TCPNumber) + fillIPv4Default(packet, uint16(types.IPv4MinLen+types.TCPMinLen+plSize), types.TCPNumber) packet.ParseL4ForIPv4() - packet.GetTCPNoCheck().DataOff = TCPMinDataOffset + packet.GetTCPNoCheck().DataOff = types.TCPMinDataOffset packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(packet.GetTCPNoCheck().DataOff&0xf0)>>2) if hwtxchecksum { packet.GetIPv4NoCheck().HdrChecksum = 0 - low.SetTXIPv4TCPOLFlags(packet.CMbuf, EtherLen, IPv4MinLen) + low.SetTXIPv4TCPOLFlags(packet.CMbuf, types.EtherLen, types.IPv4MinLen) } return true } @@ -589,22 +586,22 @@ func InitEmptyIPv4TCPPacket(packet *Packet, plSize uint) bool { // header has minimum length. In fact length can be higher due to optional fields. // Now setting optional fields explicitly is not supported. func InitEmptyIPv4UDPPacket(packet *Packet, plSize uint) bool { - bufSize := plSize + EtherLen + IPv4MinLen + UDPLen + bufSize := plSize + types.EtherLen + types.IPv4MinLen + types.UDPLen if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyIPv4UDPPacket: Cannot append mbuf") return false } - packet.Ether.EtherType = SwapBytesUint16(IPV4Number) - packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + IPv4MinLen + UDPLen) + packet.Ether.EtherType = SwapBytesUint16(types.IPV4Number) + packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + types.IPv4MinLen + types.UDPLen) packet.ParseL3() - fillIPv4Default(packet, uint16(IPv4MinLen+UDPLen+plSize), UDPNumber) + fillIPv4Default(packet, uint16(types.IPv4MinLen+types.UDPLen+plSize), types.UDPNumber) packet.ParseL4ForIPv4() - packet.GetUDPNoCheck().DgramLen = SwapBytesUint16(uint16(UDPLen + plSize)) + packet.GetUDPNoCheck().DgramLen = SwapBytesUint16(uint16(types.UDPLen + plSize)) if hwtxchecksum { packet.GetIPv4NoCheck().HdrChecksum = 0 - low.SetTXIPv4UDPOLFlags(packet.CMbuf, EtherLen, IPv4MinLen) + low.SetTXIPv4UDPOLFlags(packet.CMbuf, types.EtherLen, types.IPv4MinLen) } return true } @@ -614,16 +611,16 @@ func InitEmptyIPv4UDPPacket(packet *Packet, plSize uint) bool { // header has minimum length. In fact length can be higher due to optional fields. // Now setting optional fields explicitly is not supported. func InitEmptyIPv4ICMPPacket(packet *Packet, plSize uint) bool { - bufSize := plSize + EtherLen + IPv4MinLen + ICMPLen + bufSize := plSize + types.EtherLen + types.IPv4MinLen + types.ICMPLen if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyIPv4ICMPPacket: Cannot append mbuf") return false } - packet.Ether.EtherType = SwapBytesUint16(IPV4Number) - packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + IPv4MinLen + ICMPLen) + packet.Ether.EtherType = SwapBytesUint16(types.IPV4Number) + packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + types.IPv4MinLen + types.ICMPLen) packet.ParseL3() - fillIPv4Default(packet, uint16(IPv4MinLen+ICMPLen+plSize), ICMPNumber) + fillIPv4Default(packet, uint16(types.IPv4MinLen+types.ICMPLen+plSize), types.ICMPNumber) packet.ParseL4ForIPv4() return true } @@ -634,21 +631,21 @@ func InitEmptyIPv4ICMPPacket(packet *Packet, plSize uint) bool { // Now setting optional fields explicitly is not supported. func InitEmptyIPv6TCPPacket(packet *Packet, plSize uint) bool { // TODO support variable header length (ask header length from user) - bufSize := plSize + EtherLen + IPv6Len + TCPMinLen + bufSize := plSize + types.EtherLen + types.IPv6Len + types.TCPMinLen if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyIPv6TCPPacket: Cannot append mbuf") return false } - packet.Ether.EtherType = SwapBytesUint16(IPV6Number) + packet.Ether.EtherType = SwapBytesUint16(types.IPV6Number) packet.ParseL3() - fillIPv6Default(packet, uint16(TCPMinLen+plSize), TCPNumber) + fillIPv6Default(packet, uint16(types.TCPMinLen+plSize), types.TCPNumber) packet.ParseL4ForIPv6() - packet.GetTCPNoCheck().DataOff = TCPMinDataOffset + packet.GetTCPNoCheck().DataOff = types.TCPMinDataOffset packet.Data = unsafe.Pointer(uintptr(packet.L4) + uintptr(packet.GetTCPNoCheck().DataOff&0xf0)>>2) if hwtxchecksum { - low.SetTXIPv6TCPOLFlags(packet.CMbuf, EtherLen, IPv6Len) + low.SetTXIPv6TCPOLFlags(packet.CMbuf, types.EtherLen, types.IPv6Len) } return true } @@ -658,21 +655,21 @@ func InitEmptyIPv6TCPPacket(packet *Packet, plSize uint) bool { // header has minimum length. In fact length can be higher due to optional fields. // Now setting optional fields explicitly is not supported. func InitEmptyIPv6UDPPacket(packet *Packet, plSize uint) bool { - bufSize := plSize + EtherLen + IPv6Len + UDPLen + bufSize := plSize + types.EtherLen + types.IPv6Len + types.UDPLen if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyIPv6UDPPacket: Cannot append mbuf") return false } - packet.Ether.EtherType = SwapBytesUint16(IPV6Number) - packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + IPv6Len + UDPLen) + packet.Ether.EtherType = SwapBytesUint16(types.IPV6Number) + packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + types.IPv6Len + types.UDPLen) packet.ParseL3() - fillIPv6Default(packet, uint16(UDPLen+plSize), UDPNumber) + fillIPv6Default(packet, uint16(types.UDPLen+plSize), types.UDPNumber) packet.ParseL4ForIPv6() - packet.GetUDPNoCheck().DgramLen = SwapBytesUint16(uint16(UDPLen + plSize)) + packet.GetUDPNoCheck().DgramLen = SwapBytesUint16(uint16(types.UDPLen + plSize)) if hwtxchecksum { - low.SetTXIPv6UDPOLFlags(packet.CMbuf, EtherLen, IPv6Len) + low.SetTXIPv6UDPOLFlags(packet.CMbuf, types.EtherLen, types.IPv6Len) } return true } @@ -680,16 +677,16 @@ func InitEmptyIPv6UDPPacket(packet *Packet, plSize uint) bool { // InitEmptyIPv6ICMPPacket initializes input packet with preallocated plSize of bytes for payload // and init pointers to Ethernet, IPv6 and ICMP headers. func InitEmptyIPv6ICMPPacket(packet *Packet, plSize uint) bool { - bufSize := plSize + EtherLen + IPv6Len + ICMPLen + bufSize := plSize + types.EtherLen + types.IPv6Len + types.ICMPLen if low.AppendMbuf(packet.CMbuf, bufSize) == false { LogWarning(Debug, "InitEmptyIPv6ICMPPacket: Cannot append mbuf") return false } - packet.Ether.EtherType = SwapBytesUint16(IPV6Number) - packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + IPv6Len + ICMPLen) + packet.Ether.EtherType = SwapBytesUint16(types.IPV6Number) + packet.Data = unsafe.Pointer(uintptr(packet.unparsed()) + types.IPv6Len + types.ICMPLen) packet.ParseL3() - fillIPv6Default(packet, uint16(ICMPLen+plSize), ICMPv6Number) + fillIPv6Default(packet, uint16(types.ICMPLen+plSize), types.ICMPv6Number) packet.ParseL4ForIPv6() return true } @@ -704,7 +701,7 @@ func SwapBytesUint32(x uint32) uint32 { return ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24) } -func SwapBytesIPv4Addr(x IPv4Address) IPv4Address { +func SwapBytesIPv4Addr(x types.IPv4Address) types.IPv4Address { return ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24) } @@ -838,8 +835,8 @@ func SetNonPerfMempool(m *low.Mempool) { } type LPM struct { - tbl24 *([MaxLength]IPv4Address) - tbl8 *([MaxLength]IPv4Address) + tbl24 *([types.MaxLength]types.IPv4Address) + tbl8 *([types.MaxLength]types.IPv4Address) lpm unsafe.Pointer //C.struct_rte_lpm } @@ -860,7 +857,7 @@ func CreateLPM(name string, socket uint8, maxRules uint32, numberTbl8 uint32) *L // Heavily based on DPDK rte_lpm_lookup with constants from there // No error checking (lpm == NULL or nextHop == NULL) due to performance // User should check it manually -func (lpm *LPM) Lookup(ip IPv4Address, nextHop *IPv4Address) bool { +func (lpm *LPM) Lookup(ip types.IPv4Address, nextHop *types.IPv4Address) bool { tbl24_index := ip >> 8 tbl_entry := (*lpm.tbl24)[tbl24_index] // Copy tbl24 entry @@ -879,13 +876,13 @@ func (lpm *LPM) Lookup(ip IPv4Address, nextHop *IPv4Address) bool { // Add adds longest prefix match rule with specified ip, depth and nextHop // inside LPM table. Returns 0 if success and negative value otherwise -func (lpm *LPM) Add(ip IPv4Address, depth uint8, nextHop IPv4Address) int { +func (lpm *LPM) Add(ip types.IPv4Address, depth uint8, nextHop types.IPv4Address) int { return low.AddLPMRule(lpm.lpm, ip, depth, nextHop) } // Delete removes longest prefix match rule with diven ip and depth from // LPM table. Returns 0 if success and negative value otherwise -func (lpm *LPM) Delete(ip IPv4Address, depth uint8) int { +func (lpm *LPM) Delete(ip types.IPv4Address, depth uint8) int { return low.DeleteLPMRule(lpm.lpm, ip, depth) } diff --git a/packet/packet_test.go b/packet/packet_test.go index 1acb7599..28840b3f 100644 --- a/packet/packet_test.go +++ b/packet/packet_test.go @@ -12,7 +12,7 @@ import ( "testing" "unsafe" - . "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) func init() { @@ -21,44 +21,44 @@ func init() { var MacHeader = [8]EtherHdr{ { - DAddr: [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, - SAddr: [6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, - EtherType: SwapBytesUint16(IPV4Number), + DAddr: types.MACAddress{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + SAddr: types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, + EtherType: SwapBytesUint16(types.IPV4Number), }, { - DAddr: [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, - SAddr: [6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, - EtherType: SwapBytesUint16(IPV4Number), + DAddr: types.MACAddress{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + SAddr: types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, + EtherType: SwapBytesUint16(types.IPV4Number), }, { - DAddr: [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, - SAddr: [6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x52}, - EtherType: SwapBytesUint16(IPV4Number), + DAddr: types.MACAddress{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + SAddr: types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x52}, + EtherType: SwapBytesUint16(types.IPV4Number), }, { - DAddr: [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, - SAddr: [6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x52}, - EtherType: SwapBytesUint16(IPV4Number), + DAddr: types.MACAddress{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + SAddr: types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x52}, + EtherType: SwapBytesUint16(types.IPV4Number), }, { - DAddr: [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, - SAddr: [6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x52}, - EtherType: SwapBytesUint16(IPV4Number), + DAddr: types.MACAddress{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + SAddr: types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x52}, + EtherType: SwapBytesUint16(types.IPV4Number), }, { - DAddr: [6]uint8{0x00, 0x12, 0x22, 0x33, 0x44, 0x55}, - SAddr: [6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x52}, - EtherType: SwapBytesUint16(IPV4Number), + DAddr: types.MACAddress{0x00, 0x12, 0x22, 0x33, 0x44, 0x55}, + SAddr: types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x52}, + EtherType: SwapBytesUint16(types.IPV4Number), }, { - DAddr: [6]uint8{0x10, 0x11, 0x22, 0x33, 0x44, 0x55}, - SAddr: [6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, - EtherType: SwapBytesUint16(IPV4Number), + DAddr: types.MACAddress{0x10, 0x11, 0x22, 0x33, 0x44, 0x55}, + SAddr: types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, + EtherType: SwapBytesUint16(types.IPV4Number), }, { - DAddr: [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, - SAddr: [6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, - EtherType: SwapBytesUint16(IPV4Number), + DAddr: types.MACAddress{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + SAddr: types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51}, + EtherType: SwapBytesUint16(types.IPV4Number), }, } @@ -435,8 +435,8 @@ func TestInitEmptyPacket(t *testing.T) { // Create empty packet, set Ether header fields pkt := getPacket() InitEmptyPacket(pkt, 0) - pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55} - pkt.Ether.SAddr = [6]uint8{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} + pkt.Ether.DAddr = types.MACAddress{0x00, 0x11, 0x22, 0x33, 0x44, 0x55} + pkt.Ether.SAddr = types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} // Create ground truth packet gtBuf, _ := hex.DecodeString(gtLineEther) @@ -444,7 +444,7 @@ func TestInitEmptyPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - buf := (*[1 << 30]byte)(pkt.StartAtOffset(0))[:EtherLen] + buf := (*[1 << 30]byte)(pkt.StartAtOffset(0))[:types.EtherLen] // DEEP equal for whole packet buffer if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -457,8 +457,8 @@ func TestInitEmptyIPv4Packet(t *testing.T) { InitEmptyIPv4Packet(pkt, testPlSize) dst := net.ParseIP("128.9.9.5").To4() src := net.ParseIP("127.0.0.1").To4() - pkt.GetIPv4().DstAddr = SliceToIPv4(dst) - pkt.GetIPv4().SrcAddr = SliceToIPv4(src) + pkt.GetIPv4().DstAddr = types.SliceToIPv4(dst) + pkt.GetIPv4().SrcAddr = types.SliceToIPv4(src) ptrData := (*Packetdata)(pkt.Data) ptrData.F1 = 0xddff ptrData.F2 = 0xaabb @@ -469,7 +469,7 @@ func TestInitEmptyIPv4Packet(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + IPv4MinLen + testPlSize + size := types.EtherLen + types.IPv4MinLen + testPlSize buf := (*[1 << 30]byte)(pkt.StartAtOffset(0))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -480,7 +480,7 @@ func TestInitEmptyIPv6Packet(t *testing.T) { // Create empty packet, set IPv6 header fields pkt := getPacket() InitEmptyIPv6Packet(pkt, testPlSize) - pkt.GetIPv6().SrcAddr = [16]uint8{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbe, 0xef} + pkt.GetIPv6().SrcAddr = types.IPv6Address{0xde, 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbe, 0xef} ptrData := (*Packetdata)(pkt.Data) ptrData.F1 = 0xddff ptrData.F2 = 0xaabb @@ -490,7 +490,7 @@ func TestInitEmptyIPv6Packet(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + IPv6Len + testPlSize + size := types.EtherLen + types.IPv6Len + testPlSize buf := (*[1 << 30]byte)(pkt.StartAtOffset(0))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -512,7 +512,7 @@ func TestInitEmptyIPv4TCPPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + IPv4MinLen + TCPMinLen + testPlSize + size := types.EtherLen + types.IPv4MinLen + types.TCPMinLen + testPlSize buf := (*[1 << 30]byte)(pkt.StartAtOffset(0))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -534,7 +534,7 @@ func TestInitEmptyIPv4UDPPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + IPv4MinLen + UDPLen + testPlSize + size := types.EtherLen + types.IPv4MinLen + types.UDPLen + testPlSize buf := (*[1 << 30]byte)(pkt.StartAtOffset(0))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -556,7 +556,7 @@ func TestInitEmptyIPv6TCPPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + IPv6Len + TCPMinLen + testPlSize + size := types.EtherLen + types.IPv6Len + types.TCPMinLen + testPlSize buf := (*[1 << 30]byte)(pkt.StartAtOffset(0))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -578,7 +578,7 @@ func TestInitEmptyIPv6UDPPacket(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + IPv6Len + UDPLen + testPlSize + size := types.EtherLen + types.IPv6Len + types.UDPLen + testPlSize buf := (*[1 << 30]byte)(pkt.StartAtOffset(0))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) diff --git a/packet/utils_for_test.go b/packet/utils_for_test.go index 1006e11c..ecdcd5e5 100644 --- a/packet/utils_for_test.go +++ b/packet/utils_for_test.go @@ -8,8 +8,8 @@ import ( "net" "os" - "github.com/intel-go/nff-go/common" "github.com/intel-go/nff-go/low" + "github.com/intel-go/nff-go/types" ) // isInit is common for all tests @@ -95,27 +95,27 @@ func getIPv6ICMPTestPacket() *Packet { func getARPRequestTestPacket() *Packet { pkt := getPacket() - sha := common.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} - spa := common.SliceToIPv4(net.ParseIP("127.0.0.1").To4()) - tpa := common.SliceToIPv4(net.ParseIP("128.9.9.5").To4()) + sha := types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} + spa := types.SliceToIPv4(net.ParseIP("127.0.0.1").To4()) + tpa := types.SliceToIPv4(net.ParseIP("128.9.9.5").To4()) InitARPRequestPacket(pkt, sha, spa, tpa) return pkt } func initEtherAddrs(pkt *Packet) { - pkt.Ether.SAddr = common.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} - pkt.Ether.DAddr = common.MACAddress{0x0, 0x11, 0x22, 0x33, 0x44, 0x55} + pkt.Ether.SAddr = types.MACAddress{0x01, 0x11, 0x21, 0x31, 0x41, 0x51} + pkt.Ether.DAddr = types.MACAddress{0x0, 0x11, 0x22, 0x33, 0x44, 0x55} } func initIPv4Addrs(pkt *Packet) { - pkt.GetIPv4().SrcAddr = common.SliceToIPv4(net.ParseIP("127.0.0.1").To4()) - pkt.GetIPv4().DstAddr = common.SliceToIPv4(net.ParseIP("128.9.9.5").To4()) + pkt.GetIPv4().SrcAddr = types.SliceToIPv4(net.ParseIP("127.0.0.1").To4()) + pkt.GetIPv4().DstAddr = types.SliceToIPv4(net.ParseIP("128.9.9.5").To4()) } func initIPv6Addrs(pkt *Packet) { - copy(pkt.GetIPv6().SrcAddr[:], net.ParseIP("dead::beaf")[:common.IPv6AddrLen]) - copy(pkt.GetIPv6().DstAddr[:], net.ParseIP("dead::beaf")[:common.IPv6AddrLen]) + copy(pkt.GetIPv6().SrcAddr[:], net.ParseIP("dead::beaf")[:types.IPv6AddrLen]) + copy(pkt.GetIPv6().DstAddr[:], net.ParseIP("dead::beaf")[:types.IPv6AddrLen]) } func initPorts(pkt *Packet) { diff --git a/packet/vlan.go b/packet/vlan.go index 038455bc..6d397850 100644 --- a/packet/vlan.go +++ b/packet/vlan.go @@ -8,7 +8,7 @@ import ( "fmt" "unsafe" - . "github.com/intel-go/nff-go/common" + . "github.com/intel-go/nff-go/types" ) // VLANHdr 802.1Q VLAN header. We interpret it as an addition after diff --git a/packet/vlan_test.go b/packet/vlan_test.go index 2d10aedd..102123ed 100644 --- a/packet/vlan_test.go +++ b/packet/vlan_test.go @@ -11,7 +11,7 @@ import ( "testing" "unsafe" - . "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" ) func init() { @@ -23,34 +23,34 @@ var ( gtLineIPv4TCPVLAN = "00400540ef240060089fb1f3810000200800450000288a1b00004006000083972015839720811770048a0000000100000d9550107c7000000000" MacHeaderVLAN = EtherHdr{ - DAddr: [6]uint8{0x00, 0x40, 0x05, 0x40, 0xef, 0x24}, - SAddr: [6]uint8{0x00, 0x60, 0x08, 0x9f, 0xb1, 0xf3}, - EtherType: SwapBytesUint16(VLANNumber), + DAddr: types.MACAddress{0x00, 0x40, 0x05, 0x40, 0xef, 0x24}, + SAddr: types.MACAddress{0x00, 0x60, 0x08, 0x9f, 0xb1, 0xf3}, + EtherType: SwapBytesUint16(types.VLANNumber), } VlanTag = VLANHdr{ TCI: SwapBytesUint16(32), - EtherType: SwapBytesUint16(IPV4Number), + EtherType: SwapBytesUint16(types.IPV4Number), } IPv4HeaderVLAN = IPv4Hdr{ VersionIhl: 0x45, PacketID: SwapBytesUint16(35355), TimeToLive: uint8(64), - NextProtoID: TCPNumber, + NextProtoID: types.TCPNumber, HdrChecksum: 0, - SrcAddr: SliceToIPv4([]byte(net.ParseIP("131.151.32.21").To4())), - DstAddr: SliceToIPv4([]byte(net.ParseIP("131.151.32.129").To4())), - TotalLength: SwapBytesUint16(uint16(IPv4MinLen + TCPMinLen)), + SrcAddr: types.SliceToIPv4([]byte(net.ParseIP("131.151.32.21").To4())), + DstAddr: types.SliceToIPv4([]byte(net.ParseIP("131.151.32.129").To4())), + TotalLength: SwapBytesUint16(uint16(types.IPv4MinLen + types.TCPMinLen)), } IPv6HeaderVLAN = IPv6Hdr{ VtcFlow: SwapBytesUint32(0x60 << 24), HopLimits: 255, - Proto: NoNextHeader, - SrcAddr: [16]byte{0x26, 0x07, 0xf2, 0xc0, 0xf0, 0x0f, + Proto: types.NoNextHeader, + SrcAddr: types.IPv6Address{0x26, 0x07, 0xf2, 0xc0, 0xf0, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xce, 0xb0, 0x0c}, - DstAddr: [16]byte{0x26, 0x07, 0xf2, 0xc0, 0xf0, 0x0f, + DstAddr: types.IPv6Address{0x26, 0x07, 0xf2, 0xc0, 0xf0, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xce, 0xb0, 0x0c}, } @@ -59,7 +59,7 @@ var ( DstPort: SwapBytesUint16(1162), SentSeq: SwapBytesUint32(1), RecvAck: SwapBytesUint32(3477), - TCPFlags: TCPFlagAck, + TCPFlags: types.TCPFlagAck, RxWin: SwapBytesUint16(31856), Cksum: 0, DataOff: 0x50, @@ -67,14 +67,14 @@ var ( ARPHeaderVLAN = ARPHdr{ HType: SwapBytesUint16(1), - PType: SwapBytesUint16(IPV4Number), - HLen: EtherAddrLen, - PLen: IPv4AddrLen, + PType: SwapBytesUint16(types.IPV4Number), + HLen: types.EtherAddrLen, + PLen: types.IPv4AddrLen, Operation: SwapBytesUint16(ARPRequest), SHA: MacHeaderVLAN.SAddr, - SPA: IPv4ToBytes(IPv4HeaderVLAN.SrcAddr), - THA: [EtherAddrLen]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - TPA: IPv4ToBytes(IPv4HeaderVLAN.DstAddr), + SPA: types.IPv4ToBytes(IPv4HeaderVLAN.SrcAddr), + THA: types.MACAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + TPA: types.IPv4ToBytes(IPv4HeaderVLAN.DstAddr), } ) @@ -118,7 +118,7 @@ func TestAddVLANTag(t *testing.T) { gtPkt := getPacket() GeneratePacketFromByte(gtPkt, gtBuf) - size := EtherLen + VLANLen + IPv4MinLen + TCPMinLen + size := types.EtherLen + types.VLANLen + types.IPv4MinLen + types.TCPMinLen buf := (*[1 << 30]byte)(unsafe.Pointer(pkt.StartAtOffset(0)))[:size] if !reflect.DeepEqual(buf, gtBuf) { t.Errorf("Incorrect result:\ngot: %x, \nwant: %x\n\n", buf, gtBuf) @@ -164,24 +164,24 @@ func TestGetEtherType(t *testing.T) { InitEmptyIPv4Packet(pkt, 0) etherType := pkt.GetEtherType() - if etherType != IPV4Number { + if etherType != types.IPV4Number { t.Errorf("Incorrect GetEtherType result:\ngot: %x, \nwant: %x\n\n", - etherType, IPV4Number) + etherType, types.IPV4Number) t.FailNow() } pkt.AddVLANTag(12) etherType = pkt.GetEtherType() - if etherType != IPV4Number { + if etherType != types.IPV4Number { t.Errorf("Incorrect GetEtherType result after vlan add:\ngot: %x, \nwant: %x\n\n", - etherType, IPV4Number) + etherType, types.IPV4Number) t.FailNow() } etherType = SwapBytesUint16(pkt.Ether.EtherType) - if etherType != VLANNumber { + if etherType != types.VLANNumber { t.Errorf("Incorrect pkt.Ether.EtherType after vlan add:\ngot: %x, \nwant: %x\n\n", - etherType, VLANNumber) + etherType, types.VLANNumber) t.FailNow() } } diff --git a/test/performance/ipsec.go b/test/performance/ipsec.go index cf7cb9ec..b6ef07bf 100644 --- a/test/performance/ipsec.go +++ b/test/performance/ipsec.go @@ -11,9 +11,9 @@ import ( "hash" "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" ) func main() { @@ -67,8 +67,8 @@ const mode1230 = 1230 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 @@ -90,8 +90,8 @@ func decapsulation(currentPacket *packet.Packet, context flow.UserContext) bool // Security Association switch packet.SwapBytesUint32(currentESPHeader.SPI) { case mode1230: - 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 } @@ -157,16 +157,16 @@ func encapsulationSPI123(currentPacket *packet.Packet, context0 flow.UserContext currentESPTail := (*espTail)(currentPacket.StartAtOffset(uintptr(newLength) - espTailLen)) 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/test/performance/latency.go b/test/performance/latency.go index 5bed3d07..865571f1 100644 --- a/test/performance/latency.go +++ b/test/performance/latency.go @@ -14,9 +14,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" ) // This is 1 part of latency test @@ -35,7 +35,7 @@ var ( passedLimit uint64 = 80 packetSize uint64 = 128 - servDataSize uint64 = common.EtherLen + common.IPv4MinLen + common.UDPLen + crcLen + servDataSize uint64 = types.EtherLen + types.IPv4MinLen + types.UDPLen + crcLen outport uint16 inport uint16 diff --git a/test/performance/perf_gen.go b/test/performance/perf_gen.go index f7f6cf81..a6d046ee 100644 --- a/test/performance/perf_gen.go +++ b/test/performance/perf_gen.go @@ -6,9 +6,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 size uint @@ -33,7 +33,7 @@ func main() { flag.Parse() pkts := uint64(speed * 1000 * 1000 / 8 / (size + 20)) - size = size - EtherLen - IPv4MinLen - TCPMinLen - 4 /* Ethernet checksum length*/ + size = size - types.EtherLen - types.IPv4MinLen - types.TCPMinLen - 4 /* Ethernet checksum length*/ flow.SystemInit(nil) @@ -54,8 +54,8 @@ func generatePacket(pkt *packet.Packet, context flow.UserContext) { ipv4 := pkt.GetIPv4() tcp := pkt.GetTCPForIPv4() - ipv4.DstAddr = packet.SwapBytesIPv4Addr(IPv4Address(r)) - ipv4.SrcAddr = packet.SwapBytesIPv4Addr(IPv4Address(r + 15)) + ipv4.DstAddr = packet.SwapBytesIPv4Addr(types.IPv4Address(r)) + ipv4.SrcAddr = packet.SwapBytesIPv4Addr(types.IPv4Address(r + 15)) tcp.DstPort = packet.SwapBytesUint16(r + 25) tcp.SrcPort = packet.SwapBytesUint16(r + 35) diff --git a/test/performance/perf_main.go b/test/performance/perf_main.go index 13121fea..61fd9f04 100644 --- a/test/performance/perf_main.go +++ b/test/performance/perf_main.go @@ -7,9 +7,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 ( @@ -53,10 +53,10 @@ func heavyFunc(currentPacket *packet.Packet, context flow.UserContext) { ipv4 := currentPacket.GetIPv4() if ipv4 != nil { T := ipv4.DstAddr - for j := common.IPv4Address(0); j < common.IPv4Address(load); j++ { + for j := types.IPv4Address(0); j < types.IPv4Address(load); j++ { T += j } - for i := common.IPv4Address(0); i < common.IPv4Address(loadRW); i++ { + for i := types.IPv4Address(0); i < types.IPv4Address(loadRW); i++ { ipv4.DstAddr = ipv4.SrcAddr + i } ipv4.SrcAddr = 263 + (T) diff --git a/test/performance/perf_seq.go b/test/performance/perf_seq.go index 0940408b..b57d245a 100644 --- a/test/performance/perf_seq.go +++ b/test/performance/perf_seq.go @@ -7,9 +7,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 ( @@ -83,7 +83,7 @@ func heavyFunc(currentPacket *packet.Packet, context flow.UserContext) { if ipv4 != nil { T := (ipv4.DstAddr) for j := uint(0); j < load; j++ { - T += common.IPv4Address(j) + T += types.IPv4Address(j) } ipv4.SrcAddr = 263 + (T) } diff --git a/test/stability/stabilityCommon/common.go b/test/stability/stabilityCommon/common.go index cba5930c..53ae4dd2 100644 --- a/test/stability/stabilityCommon/common.go +++ b/test/stability/stabilityCommon/common.go @@ -2,23 +2,24 @@ package stabilityCommon import ( "encoding/json" - "github.com/intel-go/nff-go/common" - "github.com/intel-go/nff-go/flow" - "github.com/intel-go/nff-go/packet" "log" "net" "os" + + "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 - dstMac0 [common.EtherAddrLen]uint8 - srcMac0 [common.EtherAddrLen]uint8 - dstMac1 [common.EtherAddrLen]uint8 - srcMac1 [common.EtherAddrLen]uint8 + dstMac0 [types.EtherAddrLen]uint8 + srcMac0 [types.EtherAddrLen]uint8 + dstMac1 [types.EtherAddrLen]uint8 + srcMac1 [types.EtherAddrLen]uint8 // First byte in MAC address has to be even because otherwise it // means multicast address which cannot be source address. - stubMac = [common.EtherAddrLen]uint8{0x10, 0x22, 0x33, 0x44, 0x55, 0x66} + stubMac = [types.EtherAddrLen]uint8{0x10, 0x22, 0x33, 0x44, 0x55, 0x66} // ModifyPacket is used to set src and dst MAC addresses for outgoing packets. ModifyPacket = []interface{}{modifyPacket0, modifyPacket1} ) @@ -26,7 +27,7 @@ var ( // ShouldBeSkipped return true for packets which are not expected to receive by test. // Return false only for expected IPv4 UDP packets. func ShouldBeSkipped(pkt *packet.Packet) bool { - if packet.SwapBytesUint16(pkt.Ether.EtherType) != common.IPV4Number { + if packet.SwapBytesUint16(pkt.Ether.EtherType) != types.IPV4Number { println("Not IPv4 packet, skip") return true } @@ -103,7 +104,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/test/stability/testCksum/testCksum.go b/test/stability/testCksum/testCksum.go index 66755930..3a8a153b 100644 --- a/test/stability/testCksum/testCksum.go +++ b/test/stability/testCksum/testCksum.go @@ -14,9 +14,9 @@ import ( "time" "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" "github.com/intel-go/nff-go/test/stability/stabilityCommon" "github.com/intel-go/nff-go/test/stability/testCksum/testCksumCommon" @@ -465,8 +465,8 @@ func initPacketIPv4(emptyPacket *packet.Packet) { func initPacketIPv6(emptyPacket *packet.Packet) { // Initialize IPv6 addresses emptyPacketIPv6 := emptyPacket.GetIPv6() - emptyPacketIPv6.SrcAddr = common.IPv6Address{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - emptyPacketIPv6.DstAddr = common.IPv6Address{17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} + emptyPacketIPv6.SrcAddr = types.IPv6Address{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + emptyPacketIPv6.DstAddr = types.IPv6Address{17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} } func initPacketUDP(emptyPacket *packet.Packet) { @@ -483,7 +483,7 @@ func initPacketTCP(emptyPacket *packet.Packet) { func initPacketICMP(emptyPacket *packet.Packet) { emptyPacketICMP := (*packet.ICMPHdr)(emptyPacket.L4) - emptyPacketICMP.Type = common.ICMPTypeEchoRequest + emptyPacketICMP.Type = types.ICMPTypeEchoRequest emptyPacketICMP.Identifier = 0xdead emptyPacketICMP.SeqNum = 0xbeef } @@ -535,12 +535,12 @@ func generateIPv4ICMP(emptyPacket *packet.Packet, rnd *rand.Rand) { pICMP := emptyPacket.GetICMPForIPv4() if hwol { pIPv4.HdrChecksum = 0 - emptyPacket.SetTXIPv4OLFlags(common.EtherLen, common.IPv4MinLen) + emptyPacket.SetTXIPv4OLFlags(types.EtherLen, types.IPv4MinLen) } else { pIPv4.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pIPv4)) } pICMP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv4ICMPChecksum(pIPv4, pICMP, - unsafe.Pointer(uintptr(unsafe.Pointer(pICMP))+common.ICMPLen))) + unsafe.Pointer(uintptr(unsafe.Pointer(pICMP))+types.ICMPLen))) } func generateIPv6UDP(emptyPacket *packet.Packet, rnd *rand.Rand) { diff --git a/test/stability/testCksum/testCksumCommon/testCksumCommon.go b/test/stability/testCksum/testCksumCommon/testCksumCommon.go index 7d11d0bd..ae7da58a 100644 --- a/test/stability/testCksum/testCksumCommon/testCksumCommon.go +++ b/test/stability/testCksum/testCksumCommon/testCksumCommon.go @@ -5,8 +5,8 @@ package testCksumCommon import ( - "github.com/intel-go/nff-go/common" "github.com/intel-go/nff-go/packet" + "github.com/intel-go/nff-go/types" ) // Packetdata is a structure for packet pointer cast. @@ -23,7 +23,7 @@ var ( func CheckPacketChecksums(p *packet.Packet) bool { status := false - if p.GetEtherType() == common.IPV4Number { + if p.GetEtherType() == types.IPV4Number { pIPv4 := p.GetIPv4CheckVLAN() csum := packet.CalculateIPv4Checksum(pIPv4) l3status := true @@ -31,7 +31,7 @@ func CheckPacketChecksums(p *packet.Packet) bool { println("IPv4 checksum mismatch", packet.SwapBytesUint16(pIPv4.HdrChecksum), "should be", csum) l3status = false } - if pIPv4.NextProtoID == common.UDPNumber { + if pIPv4.NextProtoID == types.UDPNumber { pUDP := p.GetUDPForIPv4() csum := packet.CalculateIPv4UDPChecksum(pIPv4, pUDP, p.Data) if packet.SwapBytesUint16(pUDP.DgramCksum) != csum { @@ -44,7 +44,7 @@ func CheckPacketChecksums(p *packet.Packet) bool { } else { status = l3status } - } else if pIPv4.NextProtoID == common.TCPNumber { + } else if pIPv4.NextProtoID == types.TCPNumber { pTCP := p.GetTCPForIPv4() csum := packet.CalculateIPv4TCPChecksum(pIPv4, pTCP, p.Data) if packet.SwapBytesUint16(pTCP.Cksum) != csum { @@ -57,7 +57,7 @@ func CheckPacketChecksums(p *packet.Packet) bool { } else { status = l3status } - } else if pIPv4.NextProtoID == common.ICMPNumber { + } else if pIPv4.NextProtoID == types.ICMPNumber { pICMP := p.GetICMPForIPv4() csum := packet.CalculateIPv4ICMPChecksum(pIPv4, pICMP, p.Data) if packet.SwapBytesUint16(pICMP.Cksum) != csum { @@ -68,9 +68,9 @@ func CheckPacketChecksums(p *packet.Packet) bool { } else { println("Unknown IPv4 protocol number", pIPv4.NextProtoID) } - } else if p.GetEtherType() == common.IPV6Number { + } else if p.GetEtherType() == types.IPV6Number { pIPv6 := p.GetIPv6CheckVLAN() - if pIPv6.Proto == common.UDPNumber { + if pIPv6.Proto == types.UDPNumber { pUDP := p.GetUDPForIPv6() csum := packet.CalculateIPv6UDPChecksum(pIPv6, pUDP, p.Data) if packet.SwapBytesUint16(pUDP.DgramCksum) != csum { @@ -83,7 +83,7 @@ func CheckPacketChecksums(p *packet.Packet) bool { } else { status = true } - } else if pIPv6.Proto == common.TCPNumber { + } else if pIPv6.Proto == types.TCPNumber { pTCP := p.GetTCPForIPv6() csum := packet.CalculateIPv6TCPChecksum(pIPv6, pTCP, p.Data) if packet.SwapBytesUint16(pTCP.Cksum) != csum { @@ -96,7 +96,7 @@ func CheckPacketChecksums(p *packet.Packet) bool { } else { status = true } - } else if pIPv6.Proto == common.ICMPv6Number { + } else if pIPv6.Proto == types.ICMPv6Number { pICMP := p.GetICMPForIPv6() csum := packet.CalculateIPv6ICMPChecksum(pIPv6, pICMP, p.Data) if packet.SwapBytesUint16(pICMP.Cksum) != csum { @@ -116,32 +116,32 @@ func CheckPacketChecksums(p *packet.Packet) bool { // CalculateChecksum calculates checksum and writes to fields of packet. func CalculateChecksum(p *packet.Packet) { - if p.GetEtherType() == common.IPV4Number { + if p.GetEtherType() == types.IPV4Number { pIPv4 := p.GetIPv4NoCheck() pIPv4.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(pIPv4)) - if pIPv4.NextProtoID == common.UDPNumber { + if pIPv4.NextProtoID == types.UDPNumber { pUDP := p.GetUDPForIPv4() pUDP.DgramCksum = packet.SwapBytesUint16(packet.CalculateIPv4UDPChecksum(pIPv4, pUDP, p.Data)) - } else if pIPv4.NextProtoID == common.TCPNumber { + } else if pIPv4.NextProtoID == types.TCPNumber { pTCP := p.GetTCPForIPv4() pTCP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv4TCPChecksum(pIPv4, pTCP, p.Data)) - } else if pIPv4.NextProtoID == common.ICMPNumber { + } else if pIPv4.NextProtoID == types.ICMPNumber { pICMP := p.GetICMPForIPv4() pICMP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv4ICMPChecksum(pIPv4, pICMP, p.Data)) } else { println("Unknown IPv4 protocol number", pIPv4.NextProtoID) println("TEST FAILED") } - } else if p.GetEtherType() == common.IPV6Number { + } else if p.GetEtherType() == types.IPV6Number { pIPv6 := p.GetIPv6NoCheck() - if pIPv6.Proto == common.UDPNumber { + if pIPv6.Proto == types.UDPNumber { pUDP := p.GetUDPForIPv6() pUDP.DgramCksum = packet.SwapBytesUint16(packet.CalculateIPv6UDPChecksum(pIPv6, pUDP, p.Data)) - } else if pIPv6.Proto == common.TCPNumber { + } else if pIPv6.Proto == types.TCPNumber { pTCP := p.GetTCPForIPv6() pTCP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv6TCPChecksum(pIPv6, pTCP, p.Data)) - } else if pIPv6.Proto == common.ICMPv6Number { + } else if pIPv6.Proto == types.ICMPv6Number { pICMP := p.GetICMPForIPv6() pICMP.Cksum = packet.SwapBytesUint16(packet.CalculateIPv6ICMPChecksum(pIPv6, pICMP, p.Data)) } else { diff --git a/test/stability/testMerge/testMerge.go b/test/stability/testMerge/testMerge.go index 2bd07968..5a0ed7ad 100644 --- a/test/stability/testMerge/testMerge.go +++ b/test/stability/testMerge/testMerge.go @@ -12,10 +12,10 @@ 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/test/stability/stabilityCommon" + "github.com/intel-go/nff-go/types" ) // Test with testScenario=1: @@ -64,8 +64,8 @@ var ( // Usually when writing multibyte fields to packet, we should make // sure that byte order in packet buffer is correct and swap bytes if needed. // Here for testing purposes we use addresses with bytes swapped by hand. - ipv4addr1 common.IPv4Address = 0x0100007f // 127.0.0.1 - ipv4addr2 common.IPv4Address = 0x05090980 // 128.9.9.5 + ipv4addr1 types.IPv4Address = 0x0100007f // 127.0.0.1 + ipv4addr2 types.IPv4Address = 0x05090980 // 128.9.9.5 testDoneEvent *sync.Cond progStart time.Time diff --git a/types/Makefile b/types/Makefile new file mode 100644 index 00000000..bf306e09 --- /dev/null +++ b/types/Makefile @@ -0,0 +1,15 @@ +# Copyright 2019 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 +include $(PATH_TO_MK)/include.mk + +.PHONY: testing +testing: check-pktgen + go test + +.PHONY: coverage +coverage: + go test -cover -coverprofile=c.out + go tool cover -html=c.out -o common_coverage.html diff --git a/types/const.go b/types/const.go new file mode 100644 index 00000000..97ec547d --- /dev/null +++ b/types/const.go @@ -0,0 +1,97 @@ +// 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 types + +import ( + "math" +) + +// 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 +) + +// 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 +) diff --git a/types/ipv4.go b/types/ipv4.go new file mode 100644 index 00000000..fea89bb0 --- /dev/null +++ b/types/ipv4.go @@ -0,0 +1,59 @@ +// 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 types + +import ( + "encoding/json" + "fmt" + "net" +) + +type IPv4Address uint32 + +// BytesToIPv4 converts four element address to IPv4Address representation +func BytesToIPv4(a byte, b byte, c byte, d byte) IPv4Address { + return IPv4Address(d)<<24 | IPv4Address(c)<<16 | IPv4Address(b)<<8 | IPv4Address(a) +} + +// ArrayToIPv4 converts four element array to IPv4Address representation +func ArrayToIPv4(a [IPv4AddrLen]byte) IPv4Address { + return IPv4Address(a[3])<<24 | IPv4Address(a[2])<<16 | IPv4Address(a[1])<<8 | IPv4Address(a[0]) +} + +// SliceToIPv4 converts four element slice to IPv4Address representation +func SliceToIPv4(s []byte) IPv4Address { + return IPv4Address(s[3])<<24 | IPv4Address(s[2])<<16 | IPv4Address(s[1])<<8 | IPv4Address(s[0]) +} + +// IPv4ToBytes converts four element address to IPv4Address representation +func IPv4ToBytes(v IPv4Address) [IPv4AddrLen]byte { + return [IPv4AddrLen]uint8{byte(v), byte(v >> 8), byte(v >> 16), byte(v >> 24)} +} + +func (addr IPv4Address) String() string { + return fmt.Sprintf("%d.%d.%d.%d", byte(addr), byte(addr>>8), byte(addr>>16), byte(addr>>24)) +} + +func IPv4ArrayToString(addr [IPv4AddrLen]uint8) string { + return fmt.Sprintf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]) +} + +// UnmarshalJSON parses IPv4 address. +func (out *IPv4Address) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + if ip := net.ParseIP(s); ip != nil { + ipv4 := ip.To4() + if ipv4 == nil { + return fmt.Errorf("Bad IPv4 address %s", s) + } + *out = BytesToIPv4(ipv4[0], ipv4[1], ipv4[2], ipv4[3]) + return nil + } + return fmt.Errorf("Failed to parse address %s", s) +} diff --git a/types/ipv6.go b/types/ipv6.go new file mode 100644 index 00000000..21a62aa8 --- /dev/null +++ b/types/ipv6.go @@ -0,0 +1,39 @@ +// 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 types + +import ( + "encoding/json" + "fmt" + "net" +) + +type IPv6Address [IPv6AddrLen]uint8 + +func (addr IPv6Address) String() string { + return fmt.Sprintf("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5], addr[6], addr[7], + addr[8], addr[9], addr[10], addr[11], + addr[12], addr[13], addr[14], addr[15]) +} + +// UnmarshalJSON parses IPv6 address. +func (out *IPv6Address) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + if ip := net.ParseIP(s); ip != nil { + ipv6 := ip.To16() + if ipv6 == nil { + return fmt.Errorf("Bad IPv6 address %s", s) + } + copy((*out)[:], ipv6) + return nil + } + return fmt.Errorf("Failed to parse address %s", s) +} diff --git a/types/mac.go b/types/mac.go new file mode 100644 index 00000000..27eaea23 --- /dev/null +++ b/types/mac.go @@ -0,0 +1,16 @@ +// 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 types + +import ( + "fmt" +) + +type MACAddress [EtherAddrLen]uint8 + +// MACToString return MAC address like string +func (mac MACAddress) String() string { + return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) +} From a2c34658f85ac2891f4cf24e7e97b21f7315a58a Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Wed, 12 Dec 2018 13:05:59 -0800 Subject: [PATCH 14/24] Implemented load balancer with 5-tuple hashing Workers are selected randomly (evenly) based on 5-tuple hash. --- examples/Makefile | 7 +- examples/lb/Makefile | 8 ++ examples/lb/balancer.go | 163 +++++++++++++++++++++++++++++++++++ examples/lb/config.go | 68 +++++++++++++++ examples/lb/main/.gitignore | 1 + examples/lb/main/Makefile | 11 +++ examples/lb/main/config.json | 24 ++++++ examples/lb/main/lb.go | 34 ++++++++ examples/lb/util.go | 27 ++++++ packet/gre.go | 34 ++++++++ packet/neigh.go | 100 +++++++++++++++++++++ types/const.go | 2 + types/subnet.go | 129 +++++++++++++++++++++++++++ 13 files changed, 605 insertions(+), 3 deletions(-) create mode 100644 examples/lb/Makefile create mode 100644 examples/lb/balancer.go create mode 100644 examples/lb/config.go create mode 100644 examples/lb/main/.gitignore create mode 100644 examples/lb/main/Makefile create mode 100644 examples/lb/main/config.json create mode 100644 examples/lb/main/lb.go create mode 100644 examples/lb/util.go create mode 100644 packet/gre.go create mode 100644 packet/neigh.go create mode 100644 types/subnet.go diff --git a/examples/Makefile b/examples/Makefile index 85da9530..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 generate OSforwarding -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/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/lb/main/Makefile b/examples/lb/main/Makefile new file mode 100644 index 00000000..7a3f7af2 --- /dev/null +++ b/examples/lb/main/Makefile @@ -0,0 +1,11 @@ +# 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 = lb +EXECUTABLES = lb + +lb: lb.go ../config.go + +include $(PATH_TO_MK)/leaf.mk 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/packet/gre.go b/packet/gre.go new file mode 100644 index 00000000..be9d7458 --- /dev/null +++ b/packet/gre.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 packet + +import ( + "fmt" + + "github.com/intel-go/nff-go/types" +) + +type GREHdr struct { + Flags uint16 + NextProto uint16 +} + +func (hdr *GREHdr) String() string { + return fmt.Sprintf("GRE: flags = 0x%04x, embedded protocol = 0x%04x", + hdr.Flags, hdr.NextProto) +} + +// GetGREForIPv4 casts L4 pointer to *GREHdr type. +func (packet *Packet) GetGREForIPv4() *GREHdr { + if packet.GetIPv4NoCheck().NextProtoID == types.GRENumber { + return (*GREHdr)(packet.L4) + } + return nil +} + +// GetGRENoCheck casts L4 pointer to *GREHdr type. +func (packet *Packet) GetGRENoCheck() *GREHdr { + return (*GREHdr)(packet.L4) +} diff --git a/packet/neigh.go b/packet/neigh.go new file mode 100644 index 00000000..48ae43f3 --- /dev/null +++ b/packet/neigh.go @@ -0,0 +1,100 @@ +// 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 packet + +import ( + "fmt" + "sync" + + "github.com/intel-go/nff-go/common" + "github.com/intel-go/nff-go/types" +) + +type NeighboursLookupTable struct { + portIndex uint16 + ipv4Table sync.Map + ipv6Table sync.Map + interfaceMAC types.MACAddress + ipv4InterfaceAddr types.IPv4Address + ipv6InterfaceAddr types.IPv6Address +} + +func NewNeighbourTable(index uint16, mac types.MACAddress, ipv4 types.IPv4Address, ipv6 types.IPv6Address) *NeighboursLookupTable { + return &NeighboursLookupTable{ + portIndex: index, + interfaceMAC: mac, + ipv4InterfaceAddr: ipv4, + ipv6InterfaceAddr: ipv6, + } +} + +// HandleIPv4ARPRequest processes IPv4 ARP request and reply packets +// and sends an ARP response (if needed) to the same interface. Packet +// has to have L3 parsed. If ARP request packet has VLAN tag, VLAN tag +// is copied into reply packet. +func (table *NeighboursLookupTable) HandleIPv4ARPPacket(pkt *Packet) error { + arp := pkt.GetARPNoCheck() + + if SwapBytesUint16(arp.Operation) != ARPRequest { + // Handle ARP reply and record information in lookup table + if SwapBytesUint16(arp.Operation) == ARPReply { + ipv4 := types.ArrayToIPv4(arp.SPA) + table.ipv4Table.Store(ipv4, arp.SHA) + } + return nil + } + + // Check that someone is asking about MAC of my IP address and HW + // address is blank in request + if types.BytesToIPv4(arp.TPA[0], arp.TPA[1], arp.TPA[2], arp.TPA[3]) != table.ipv4InterfaceAddr { + return fmt.Errorf("Warning! Got an ARP packet with target IPv4 address %s different from IPv4 address on interface. Should be %s. ARP request ignored.", types.IPv4ArrayToString(arp.TPA), table.ipv4InterfaceAddr.String()) + } + if arp.THA != (types.MACAddress{}) { + return fmt.Errorf("Warning! Got an ARP packet with non-zero MAC address %s. ARP request ignored.", arp.THA.String()) + } + + // Prepare an answer to this request + answerPacket, err := NewPacket() + if err != nil { + common.LogFatal(common.Debug, err) + } + + InitARPReplyPacket(answerPacket, table.interfaceMAC, arp.SHA, types.ArrayToIPv4(arp.TPA), types.ArrayToIPv4(arp.SPA)) + vlan := pkt.GetVLAN() + if vlan != nil { + answerPacket.AddVLANTag(SwapBytesUint16(vlan.TCI)) + } + + answerPacket.SendPacket(table.portIndex) + return nil +} + +// LookupMACForIPv4 tries to find MAC address for specified IPv4 +// address. +func (table *NeighboursLookupTable) LookupMACForIPv4(ipv4 types.IPv4Address) (types.MACAddress, bool) { + v, found := table.ipv4Table.Load(ipv4) + if found { + return v.(types.MACAddress), true + } + return [types.EtherAddrLen]byte{}, false +} + +// SendARPRequestForIPv4 sends an ARP request for specified IPv4 +// address. If specified vlan tag is not zero, ARP request packet gets +// VLAN tag assigned to it. +func (table *NeighboursLookupTable) SendARPRequestForIPv4(ipv4 types.IPv4Address, vlan uint16) { + requestPacket, err := NewPacket() + if err != nil { + common.LogFatal(common.Debug, err) + } + + InitARPRequestPacket(requestPacket, table.interfaceMAC, table.ipv4InterfaceAddr, ipv4) + + if vlan != 0 { + requestPacket.AddVLANTag(vlan) + } + + requestPacket.SendPacket(table.portIndex) +} diff --git a/types/const.go b/types/const.go index 97ec547d..ca686404 100644 --- a/types/const.go +++ b/types/const.go @@ -39,6 +39,7 @@ const ( IPNumber = 0x04 TCPNumber = 0x06 UDPNumber = 0x11 + GRENumber = 0x2f ICMPv6Number = 0x3a NoNextHeader = 0x3b ) @@ -73,6 +74,7 @@ const ( UDPLen = 8 ARPLen = 28 GTPMinLen = 8 + GRELen = 4 ) const ( diff --git a/types/subnet.go b/types/subnet.go new file mode 100644 index 00000000..bf4fa309 --- /dev/null +++ b/types/subnet.go @@ -0,0 +1,129 @@ +// 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 types + +import ( + "encoding/json" + "fmt" + "net" + "strconv" +) + +type IPv4Subnet struct { + Addr IPv4Address + Mask IPv4Address +} + +func (sn *IPv4Subnet) String() string { + // Count most significant set bits + mask := IPv4Address(1) << 31 + i := 0 + for ; i <= 32; i++ { + if sn.Mask&mask == 0 { + break + } + mask >>= 1 + } + return sn.Addr.String() + "/" + strconv.Itoa(i) +} + +// UnmarshalJSON parses ipv 4 subnet details. +func (out *IPv4Subnet) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + convertIPv4 := func(in []byte, str string) (IPv4Address, error) { + if in == nil || len(in) > 4 { + return 0, fmt.Errorf("Bad IPv4 address: ", str) + } + + return BytesToIPv4(in[0], in[1], in[2], in[3]), nil + } + + if ip, ipnet, err := net.ParseCIDR(s); err == nil { + if out.Addr, err = convertIPv4(ip.To4(), s); err != nil { + return err + } + if out.Mask, err = convertIPv4(ipnet.Mask, s); err != nil { + return err + } + return nil + } + + if ip := net.ParseIP(s); ip != nil { + var err error + if out.Addr, err = convertIPv4(ip.To4(), s); err != nil { + return err + } + out.Mask = 0xffffffff + return nil + } + return fmt.Errorf("Failed to parse address ", s) +} + +// CheckIPv4AddressWithinSubnet returns true if IPv4 addr is inside of specified subnet. +func (sn *IPv4Subnet) CheckIPv4AddressWithinSubnet(addr IPv4Address) bool { + return addr&sn.Mask == sn.Addr&sn.Mask +} + +type IPv6Subnet struct { + Addr IPv6Address + Mask IPv6Address +} + +func (sn *IPv6Subnet) String() string { + // Count most significant set bits + i := 0 + for ; i <= 128; i++ { + mask := uint8(1) << uint(7-(i&7)) + if i == 128 || sn.Mask[i>>3]&mask == 0 { + break + } + } + return sn.Addr.String() + "/" + strconv.Itoa(i) +} + +// UnmarshalJSON parses ipv 6 subnet details. +func (out *IPv6Subnet) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + if ip, ipnet, err := net.ParseCIDR(s); err == nil { + if ip.To16() == nil { + return fmt.Errorf("Bad IPv6 address: %s", s) + } + copy(out.Addr[:], ip.To16()) + copy(out.Mask[:], ipnet.Mask) + return nil + } + + if ip := net.ParseIP(s); ip != nil { + if ip.To16() == nil { + return fmt.Errorf("Bad IPv6 address: %s", s) + } + copy(out.Addr[:], ip.To16()) + out.Mask = IPv6Address{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + return nil + } + return fmt.Errorf("Failed to parse address ", s) +} + +// AndIPv6Mask performs bit AND operation for IPv6 address and mask. +func (sn *IPv6Subnet) AndIPv6Mask(addr IPv6Address) IPv6Address { + var result IPv6Address + for i := range addr { + result[i] = addr[i] & sn.Mask[i] + } + return result +} + +// CheckIPv6AddressWithinSubnet returns true if IPv6 addr is inside of specified subnet. +func (sn *IPv6Subnet) CheckIPv6AddressWithinSubnet(addr IPv6Address) bool { + return sn.AndIPv6Mask(addr) == sn.AndIPv6Mask(sn.Addr) +} From bae0b7303f9c188348d98d309b6d3c0410c27437 Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Fri, 15 Feb 2019 15:02:31 -0600 Subject: [PATCH 15/24] made burstSize changeable --- flow/flow.go | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/flow/flow.go b/flow/flow.go index 2e50e019..ba8f487a 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -46,7 +46,7 @@ var openFlowsNumber = uint32(0) var createdPorts []port var portPair map[types.IPv4Address](*port) var schedState *scheduler -var vEach [10][burstSize]uint8 +var vEach [10][vBurstSize]uint8 var devices map[string]int type Timer struct { @@ -94,7 +94,7 @@ type Func struct { vHandleFunction VectorHandleFunction vSeparateFunction VectorSeparateFunction vSplitFunction VectorSplitFunction - vFunc func([]*packet.Packet, *[burstSize]bool, *[burstSize]uint8, *Func, UserContext) + vFunc func([]*packet.Packet, *[vBurstSize]bool, *[vBurstSize]uint8, *Func, UserContext) next [](*Func) bufIndex uint @@ -117,7 +117,7 @@ type VectorGenerateFunction func([]*packet.Packet, UserContext) type HandleFunction func(*packet.Packet, UserContext) // VectorHandleFunction is a function type like HandleFunction for vector handling -type VectorHandleFunction func([]*packet.Packet, *[burstSize]bool, UserContext) +type VectorHandleFunction func([]*packet.Packet, *[vBurstSize]bool, UserContext) // SeparateFunction is a function type for user defined function which separates packets // based on some rule for two flows. Functions receives a packet from flow. @@ -126,7 +126,7 @@ type VectorHandleFunction func([]*packet.Packet, *[burstSize]bool, UserContext) type SeparateFunction func(*packet.Packet, UserContext) bool // VectorSeparateFunction is a function type like SeparateFunction for vector separation -type VectorSeparateFunction func([]*packet.Packet, *[burstSize]bool, *[burstSize]bool, UserContext) +type VectorSeparateFunction func([]*packet.Packet, *[vBurstSize]bool, *[vBurstSize]bool, UserContext) // SplitFunction is a function type for user defined function which splits packets // based in some rule for multiple flows. Function receives a packet from @@ -138,7 +138,7 @@ type VectorSeparateFunction func([]*packet.Packet, *[burstSize]bool, *[burstSize type SplitFunction func(*packet.Packet, UserContext) uint // VectorSplitFunction is a function type like SplitFunction for vector splitting -type VectorSplitFunction func([]*packet.Packet, *[burstSize]bool, *[burstSize]uint8, UserContext) +type VectorSplitFunction func([]*packet.Packet, *[vBurstSize]bool, *[vBurstSize]uint8, UserContext) // Kni is a high level struct of KNI device. The device itself is stored // in C memory in low.c and is defined by its port which is equal to port @@ -411,7 +411,12 @@ func SetUseHWCapability(capa HWCapability, use bool) { } } +// Size of operations with internal ring buffers and NIC receive/send +// Can be changed for debug and test purposes for scalar examples, not recommended const burstSize = 32 +// Size of all vectors in system. Can't be changed due to asm stickiness +// Using vector functions with vBurstSize != burstSize is undefined behaviour +const vBurstSize = 32 const reportMbits = false var sizeMultiplier uint @@ -1194,11 +1199,11 @@ func segmentProcess(parameters interface{}, inIndex []int32, stopper [2]chan int tempPackets := make([]*packet.Packet, burstSize) type pair struct { f *Func - mask [burstSize]bool + mask [vBurstSize]bool } def := make([]pair, 30, 30) - var currentMask [burstSize]bool - var answers [burstSize]uint8 + var currentMask [vBurstSize]bool + var answers [vBurstSize]uint8 tick := time.NewTicker(time.Duration(schedTime) * time.Millisecond) stopper[1] <- 2 // Answer that function is ready @@ -1555,7 +1560,7 @@ func separate(packet *packet.Packet, sc *Func, ctx UserContext) uint { return uint(low.BoolToInt(sc.sSeparateFunction(packet, ctx))) } -func vSeparate(packets []*packet.Packet, mask *[burstSize]bool, answers *[burstSize]uint8, ve *Func, ctx UserContext) { +func vSeparate(packets []*packet.Packet, mask *[vBurstSize]bool, answers *[vBurstSize]uint8, ve *Func, ctx UserContext) { ve.vSeparateFunction(packets, mask, low.IntArrayToBool(answers), ctx) } @@ -1572,7 +1577,7 @@ func partition(packet *packet.Packet, sc *Func, ctx UserContext) uint { return uint(context.currentAnswer) } -func vPartition(packets []*packet.Packet, mask *[burstSize]bool, answers *[burstSize]uint8, ve *Func, ctx UserContext) { +func vPartition(packets []*packet.Packet, mask *[vBurstSize]bool, answers *[vBurstSize]uint8, ve *Func, ctx UserContext) { context := ctx.(*partitionCtx) for i := 0; i < burstSize; i++ { if (*mask)[i] { @@ -1591,7 +1596,7 @@ func split(packet *packet.Packet, sc *Func, ctx UserContext) uint { return sc.sSplitFunction(packet, ctx) } -func vSplit(packets []*packet.Packet, mask *[burstSize]bool, answers *[burstSize]uint8, ve *Func, ctx UserContext) { +func vSplit(packets []*packet.Packet, mask *[vBurstSize]bool, answers *[vBurstSize]uint8, ve *Func, ctx UserContext) { ve.vSplitFunction(packets, mask, answers, ctx) } @@ -1600,7 +1605,7 @@ func handle(packet *packet.Packet, sc *Func, ctx UserContext) uint { return 0 } -func vHandle(packets []*packet.Packet, mask *[burstSize]bool, answers *[burstSize]uint8, ve *Func, ctx UserContext) { +func vHandle(packets []*packet.Packet, mask *[vBurstSize]bool, answers *[vBurstSize]uint8, ve *Func, ctx UserContext) { ve.vHandleFunction(packets, mask, ctx) } @@ -1608,7 +1613,7 @@ func constructSlice(packet *packet.Packet, sc *Func, ctx UserContext) uint { return sc.bufIndex } -func vConstructSlice(packets []*packet.Packet, mask *[burstSize]bool, answers *[burstSize]uint8, ve *Func, ctx UserContext) { +func vConstructSlice(packets []*packet.Packet, mask *[vBurstSize]bool, answers *[vBurstSize]uint8, ve *Func, ctx UserContext) { answers[0] = uint8(ve.bufIndex) } @@ -1772,9 +1777,9 @@ func CreateKniDevice(portId uint16, name string) (*Kni, error) { } } -func FillSliceFromMask(input []uintptr, mask *[burstSize]bool, output []uintptr) uint8 { +func FillSliceFromMask(input []uintptr, mask *[vBurstSize]bool, output []uintptr) uint8 { count := 0 - for i := 0; i < burstSize; i++ { + for i := 0; i < vBurstSize; i++ { if (*mask)[i] != false { output[count] = input[i] count++ From 54d38f005caa2dce6d60d741b46d280c8bf5775a Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Tue, 19 Feb 2019 23:11:01 -0600 Subject: [PATCH 16/24] Added Dockerfile for load balancer --- examples/lb/main/Dockerfile | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 examples/lb/main/Dockerfile diff --git a/examples/lb/main/Dockerfile b/examples/lb/main/Dockerfile new file mode 100644 index 00000000..7fb3c943 --- /dev/null +++ b/examples/lb/main/Dockerfile @@ -0,0 +1,13 @@ +# Copyright 2019 Intel Corporation. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +ARG USER_NAME +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 lb . +COPY config.json . From aec6da0be4c5be0906e35331dc5916c90bbe52b1 Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Mon, 25 Feb 2019 15:42:30 -0600 Subject: [PATCH 17/24] Comment about i40e driver --- flow/flow.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flow/flow.go b/flow/flow.go index ba8f487a..767821e3 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -413,6 +413,8 @@ func SetUseHWCapability(capa HWCapability, use bool) { // Size of operations with internal ring buffers and NIC receive/send // Can be changed for debug and test purposes for scalar examples, not recommended +// At i40e drivers burstSize should be >= 4 +// http://mails.dpdk.org/archives/dev/2016-December/052554.html const burstSize = 32 // Size of all vectors in system. Can't be changed due to asm stickiness // Using vector functions with vBurstSize != burstSize is undefined behaviour From 5ea25c59f16dddebe9fedfaeb45d7071bc4dfc04 Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Tue, 26 Feb 2019 15:16:51 -0600 Subject: [PATCH 18/24] Added channel for dynamically changing generate target speed This channel is returned from SetFastGenerator and SetVectorFastGenerator functions Value from channel is read by scheduler at each scheduler tick --- examples/antiddos/generatorForAntiDDoS.go | 2 +- examples/createPacket.go | 4 +-- examples/generate.go | 14 +++++++- examples/nffPktgen/README.md | 2 +- examples/nffPktgen/testing/dump.go | 2 +- examples/nffPktgen/testing/perfTest.go | 2 +- examples/nffPktgen/testing/sendGetBack.go | 2 +- flow/flow.go | 32 +++++++++---------- flow/scheduler.go | 13 ++++++++ test/performance/latency.go | 2 +- test/performance/perf_gen.go | 4 +-- test/stability/testCksum/testCksum.go | 5 ++- test/stability/testMerge/testMerge.go | 4 +-- .../testSingleWorkingFF.go | 2 +- 14 files changed, 59 insertions(+), 31 deletions(-) diff --git a/examples/antiddos/generatorForAntiDDoS.go b/examples/antiddos/generatorForAntiDDoS.go index 6db0bcef..4fe3bbda 100644 --- a/examples/antiddos/generatorForAntiDDoS.go +++ b/examples/antiddos/generatorForAntiDDoS.go @@ -70,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)) 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/generate.go b/examples/generate.go index d55016c9..336f9f4f 100644 --- a/examples/generate.go +++ b/examples/generate.go @@ -6,6 +6,7 @@ package main import ( "flag" + "fmt" "github.com/intel-go/nff-go/flow" "github.com/intel-go/nff-go/packet" "time" @@ -21,8 +22,9 @@ func main() { switch *mode { case 0: - firstFlow, _ := flow.SetFastGenerator(generatePacket, 3500, nil) + 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) @@ -56,3 +58,13 @@ func generatePacket2(port uint16) { 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/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/testing/dump.go b/examples/nffPktgen/testing/dump.go index e1aaf9b7..43236f44 100644 --- a/examples/nffPktgen/testing/dump.go +++ b/examples/nffPktgen/testing/dump.go @@ -28,7 +28,7 @@ func main() { context, err1 := generator.GetContext(configuration) flow.CheckFatal(err1) - outFlow, _ := flow.SetFastGenerator(generator.Generate, 100, context) + outFlow, _, _ := flow.SetFastGenerator(generator.Generate, 100, context) flow.SetHandler(outFlow, handleRecv, nil) flow.SetStopper(outFlow) flow.CheckFatal(flow.SystemStart()) diff --git a/examples/nffPktgen/testing/perfTest.go b/examples/nffPktgen/testing/perfTest.go index 317656a5..abd7d390 100644 --- a/examples/nffPktgen/testing/perfTest.go +++ b/examples/nffPktgen/testing/perfTest.go @@ -35,7 +35,7 @@ func main() { } context, err := generator.GetContext(configuration) flow.CheckFatal(err) - outFlow, _ := flow.SetFastGenerator(generator.Generate, speed, context) + outFlow, _, _ := flow.SetFastGenerator(generator.Generate, speed, context) flow.CheckFatal(flow.SetSender(outFlow, uint16(port))) flow.CheckFatal(flow.SystemStart()) } diff --git a/examples/nffPktgen/testing/sendGetBack.go b/examples/nffPktgen/testing/sendGetBack.go index 73bc0bc1..d40b631a 100644 --- a/examples/nffPktgen/testing/sendGetBack.go +++ b/examples/nffPktgen/testing/sendGetBack.go @@ -137,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/flow/flow.go b/flow/flow.go index 767821e3..76117f21 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -202,6 +202,7 @@ type generateParameters struct { generateFunction GenerateFunction vectorGenerateFunction VectorGenerateFunction mempool *low.Mempool + targetChannel chan uint64 targetSpeed float64 } @@ -215,14 +216,12 @@ func addGenerator(out low.Rings, generateFunction GenerateFunction, context User } func addFastGenerator(out low.Rings, generateFunction GenerateFunction, - vectorGenerateFunction VectorGenerateFunction, targetSpeed uint64, context UserContext) error { + vectorGenerateFunction VectorGenerateFunction, targetSpeed uint64, context UserContext) (chan uint64, error) { fTargetSpeed := float64(targetSpeed) - if fTargetSpeed <= 0 { - return common.WrapWithNFError(nil, "Target speed value should be > 0", common.BadArgument) - } else if fTargetSpeed/(1000 /*milleseconds*/ /float64(schedTime)) < float64(burstSize) { + if fTargetSpeed/(1000 /*milleseconds*/ /float64(schedTime)) < float64(burstSize) { // TargetSpeed per schedTime should be more than burstSize because one burstSize packets in // one schedTime seconds are out minimal scheduling part. We can't make generate speed less than this. - return common.WrapWithNFError(nil, "Target speed per schedTime should be more than burstSize", common.BadArgument) + return nil, common.WrapWithNFError(nil, "Target speed per schedTime should be more than burstSize", common.BadArgument) } par := new(generateParameters) par.out = out @@ -230,10 +229,11 @@ func addFastGenerator(out low.Rings, generateFunction GenerateFunction, par.mempool = low.CreateMempool("fast generate") par.vectorGenerateFunction = vectorGenerateFunction par.targetSpeed = fTargetSpeed + par.targetChannel = make(chan uint64, 1) ctx := make([]UserContext, 1, 1) ctx[0] = context schedState.addFF("fast generator", nil, nil, pFastGenerate, par, &ctx, fastGenerate, 0) - return nil + return par.targetChannel, nil } type sendParameters struct { @@ -795,26 +795,26 @@ func SetSenderReceiverKNI(IN *Flow, kni *Kni, linuxCore bool) (OUT *Flow, err er // SetFastGenerator adds clonable generate function to flow graph. // Gets user-defined generate function, target speed of generation user wants to achieve and context. -// Returns new open flow with generated packets. +// Returns new open flow with generated packets and channel that can be used for dynamically changing target speed // Function tries to achieve target speed by cloning. -func SetFastGenerator(f GenerateFunction, targetSpeed uint64, context UserContext) (OUT *Flow, err error) { +func SetFastGenerator(f GenerateFunction, targetSpeed uint64, context UserContext) (OUT *Flow, tc chan uint64, err error) { rings := low.CreateRings(burstSize*sizeMultiplier, 1) - if err := addFastGenerator(rings, f, nil, targetSpeed, context); err != nil { - return nil, err + if tc, err = addFastGenerator(rings, f, nil, targetSpeed, context); err != nil { + return nil, nil, err } - return newFlow(rings, 1), nil + return newFlow(rings, 1), tc, nil } // SetVectorFastGenerator adds clonable vector generate function to flow graph. // Gets user-defined vector generate function, target speed of generation user wants to achieve and context. -// Returns new open flow with generated packets. +// Returns new open flow with generated packets and channel that can be used for dynamically changing target speed // Function tries to achieve target speed by cloning. -func SetVectorFastGenerator(f VectorGenerateFunction, targetSpeed uint64, context UserContext) (OUT *Flow, err error) { +func SetVectorFastGenerator(f VectorGenerateFunction, targetSpeed uint64, context UserContext) (OUT *Flow, tc chan uint64, err error) { rings := low.CreateRings(burstSize*sizeMultiplier, 1) - if err := addFastGenerator(rings, nil, f, targetSpeed, context); err != nil { - return nil, err + if tc, err = addFastGenerator(rings, nil, f, targetSpeed, context); err != nil { + return nil, nil, err } - return newFlow(rings, 1), nil + return newFlow(rings, 1), tc, nil } // SetGenerator adds non-clonable generate flow function to flow graph. diff --git a/flow/scheduler.go b/flow/scheduler.go index 5b4a7a05..80365305 100644 --- a/flow/scheduler.go +++ b/flow/scheduler.go @@ -415,6 +415,19 @@ func (scheduler *scheduler) schedule(schedTime uint) { if ff.fType == segmentCopy || ff.fType == fastGenerate { ff.updateReportedState() // TODO also for debug } + if ff.fType == fastGenerate { + select { + case temp := <-(ff.Parameters.(*generateParameters)).targetChannel: + if float64(temp)/(1000 /*milliseconds*/ /float64(schedTime)) < float64(burstSize) { + // TargetSpeed per schedTime should be more than burstSize because one burstSize packets in + // one schedTime seconds are out minimal scheduling part. We can't make generate speed less than this. + common.LogWarning(common.Debug, "Target speed per schedTime should be more than burstSize - not changing") + } else { + (ff.Parameters.(*generateParameters)).targetSpeed = float64(temp) + } + default: + } + } // Firstly we check removing clones. We can remove one clone if: // 1. flow function has clones or it is fastGenerate // 2. scheduler removing is switched on diff --git a/test/performance/latency.go b/test/performance/latency.go index 865571f1..00ff6449 100644 --- a/test/performance/latency.go +++ b/test/performance/latency.go @@ -107,7 +107,7 @@ func main() { payloadSize = packetSize - servDataSize // Create packet flow - outputFlow, err := flow.SetFastGenerator(generatePackets, speed, nil) + outputFlow, _, err := flow.SetFastGenerator(generatePackets, speed, nil) flow.CheckFatal(err) flow.CheckFatal(flow.SetSender(outputFlow, uint16(*outport))) diff --git a/test/performance/perf_gen.go b/test/performance/perf_gen.go index a6d046ee..ddaf51a0 100644 --- a/test/performance/perf_gen.go +++ b/test/performance/perf_gen.go @@ -37,8 +37,8 @@ func main() { flow.SystemInit(nil) - a, _ := flow.SetFastGenerator(generatePacket, pkts/2, *new(ctx)) - b, _ := flow.SetFastGenerator(generatePacket, pkts/2, *new(ctx)) + a, _, _ := flow.SetFastGenerator(generatePacket, pkts/2, *new(ctx)) + b, _, _ := flow.SetFastGenerator(generatePacket, pkts/2, *new(ctx)) flow.SetSender(a, 0) flow.SetSender(b, 0) diff --git a/test/stability/testCksum/testCksum.go b/test/stability/testCksum/testCksum.go index 3a8a153b..9eaebd05 100644 --- a/test/stability/testCksum/testCksum.go +++ b/test/stability/testCksum/testCksum.go @@ -242,7 +242,10 @@ func executeTest(testScenario uint, shouldUseIPv4, shouldUseIPv6, shouldUseUDP, testDoneEvent = sync.NewCond(&m) // Create packet flow - generatedFlow, err := flow.SetFastGenerator(generatePacket, speed, initGenerator(13)) + generatedFlow, _, err := flow.SetFastGenerator(generatePacket, speed, initGenerator(13)) + if err != nil { + return err + } var finalFlow *flow.Flow if testScenario == generatePart { diff --git a/test/stability/testMerge/testMerge.go b/test/stability/testMerge/testMerge.go index 5a0ed7ad..49af5457 100644 --- a/test/stability/testMerge/testMerge.go +++ b/test/stability/testMerge/testMerge.go @@ -136,9 +136,9 @@ func setGetter(scenario getScenario, inputSource uint) (finalFlow *flow.Flow, er finalFlow, err = flow.SetReceiver(uint16(inputSource)) case fastGenerate: if inputSource == useGenerator1 { - finalFlow, err = flow.SetFastGenerator(generatePacketGroup, speed, &generatorParameters{isGroup1: true}) + finalFlow, _, err = flow.SetFastGenerator(generatePacketGroup, speed, &generatorParameters{isGroup1: true}) } else if inputSource == useGenerator2 { - finalFlow, err = flow.SetFastGenerator(generatePacketGroup, speed, &generatorParameters{isGroup1: false}) + finalFlow, _, err = flow.SetFastGenerator(generatePacketGroup, speed, &generatorParameters{isGroup1: false}) } else { return nil, errors.New(" setGetter: unknown generator type") } diff --git a/test/stability/testSingleWorkingFF/testSingleWorkingFF.go b/test/stability/testSingleWorkingFF/testSingleWorkingFF.go index edddb471..0b485d5c 100644 --- a/test/stability/testSingleWorkingFF/testSingleWorkingFF.go +++ b/test/stability/testSingleWorkingFF/testSingleWorkingFF.go @@ -197,7 +197,7 @@ func executeTest(configFile, target string, testScenario uint, testType uint) er testDoneEvent = sync.NewCond(&m) // Create packet flow - generatedFlow, err := flow.SetFastGenerator(generatePacket, speed, nil) + generatedFlow, _, err := flow.SetFastGenerator(generatePacket, speed, nil) if err != nil { return err } From 95c803c954fc15f933cded5e6b5baf769a1cfd1c Mon Sep 17 00:00:00 2001 From: Ilia Filippov Date: Wed, 27 Feb 2019 15:00:57 -0600 Subject: [PATCH 19/24] Added NoPacketHeadChange option to performance tests --- examples/demo/demo.go | 3 ++- packet/packet.go | 4 ++-- test/performance/perf_light.go | 7 ++++--- test/performance/perf_main.go | 7 ++++--- test/performance/perf_seq.go | 7 ++++--- 5 files changed, 16 insertions(+), 12 deletions(-) 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/packet/packet.go b/packet/packet.go index 28830515..2ad570e6 100644 --- a/packet/packet.go +++ b/packet/packet.go @@ -735,7 +735,7 @@ func (packet *Packet) GetPacketPayload() ([]byte, bool) { // EncapsulateHead adds bytes to packet. start - number of beginning byte, length - number of // added bytes. This function should be used to add bytes to the first half // of packet. Return false if error. -// You must not add StableL2 option to SystemInit for using this function safely. +// You must not add NoPacketHeadChange option to SystemInit for using this function safely. // TODO change this for scattered packet case (multiple mbufs) func (packet *Packet) EncapsulateHead(start uint, length uint) bool { if low.PrependMbuf(packet.CMbuf, length) == false { @@ -766,7 +766,7 @@ func (packet *Packet) EncapsulateTail(start uint, length uint) bool { // DecapsulateHead removes bytes from packet. start - number of beginning byte, length - number of // removed bytes. This function should be used to remove bytes from the first half // of packet. Return false if error. -// You must not add StableL2 option to SystemInit for using this function safely. +// You must not add NoPacketHeadChange option to SystemInit for using this function safely. // TODO change this for scattered packet case (multiple mbufs) func (packet *Packet) DecapsulateHead(start uint, length uint) bool { if low.AdjMbuf(packet.CMbuf, length) == false { diff --git a/test/performance/perf_light.go b/test/performance/perf_light.go index 67b2a07c..7400f3b9 100644 --- a/test/performance/perf_light.go +++ b/test/performance/perf_light.go @@ -23,9 +23,10 @@ func main() { // Initialize NFF-GO library config := flow.Config{ - DisableScheduler: *noscheduler, - DPDKArgs: []string{*dpdkLogLevel}, - CPUList: *cores, + DisableScheduler: *noscheduler, + DPDKArgs: []string{*dpdkLogLevel}, + CPUList: *cores, + NoPacketHeadChange: true, } flow.CheckFatal(flow.SystemInit(&config)) diff --git a/test/performance/perf_main.go b/test/performance/perf_main.go index 61fd9f04..5cc83cf5 100644 --- a/test/performance/perf_main.go +++ b/test/performance/perf_main.go @@ -30,9 +30,10 @@ func main() { // Initialize NFF-GO library config := flow.Config{ - DisableScheduler: *noscheduler, - DPDKArgs: []string{*dpdkLogLevel}, - CPUList: *cores, + DisableScheduler: *noscheduler, + DPDKArgs: []string{*dpdkLogLevel}, + CPUList: *cores, + NoPacketHeadChange: true, } flow.CheckFatal(flow.SystemInit(&config)) diff --git a/test/performance/perf_seq.go b/test/performance/perf_seq.go index b57d245a..3c91159a 100644 --- a/test/performance/perf_seq.go +++ b/test/performance/perf_seq.go @@ -30,9 +30,10 @@ func main() { // Initialize NFF-GO library config := flow.Config{ - DisableScheduler: *noscheduler, - DPDKArgs: []string{*dpdkLogLevel}, - CPUList: *cores, + DisableScheduler: *noscheduler, + DPDKArgs: []string{*dpdkLogLevel}, + CPUList: *cores, + NoPacketHeadChange: true, } flow.CheckFatal(flow.SystemInit(&config)) From b90e558c8dc52bcf24cc07039714e9a60513264d Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Thu, 28 Feb 2019 19:47:38 +0000 Subject: [PATCH 20/24] Added configuraton for AWS cloud network --- examples/lb/main/config-aws.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 examples/lb/main/config-aws.json 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" + ] +} From 590bb197888a6cbd59ae9738207631f4879dddbf Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Thu, 21 Jun 2018 10:31:25 -0500 Subject: [PATCH 21/24] Implemented send/receive statistic counters for #390 --- common/common.go | 6 + examples/forwarding/forwarding.go | 24 +- flow/counters.go | 424 ++++++++++++++++++++++++++++++ flow/flow.go | 137 ++++++++-- flow/scheduler.go | 16 +- low/low.go | 38 ++- low/low.h | 141 ++++++++-- 7 files changed, 720 insertions(+), 66 deletions(-) create mode 100644 flow/counters.go diff --git a/common/common.go b/common/common.go index 7c39fcb9..50631c97 100644 --- a/common/common.go +++ b/common/common.go @@ -97,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/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/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 +{{$name := .StatsName}} +{{range $key, $value := .Values}}{{end}}{{/* end range .Values */}} +
{{$key}}
` + + statsTemplateText = ` + + + + + + + + +

{{.NodeName}}

+ + + + + + + + + + + + + + + +
DataTotalDelta
Packets processed
no data
no data
Packets dropped
no data
no data
Bytes processed
no data
no data
+ + + + +
+ Show delta
+ Show total
+
+ + + + +
+
+ +` +) + +var ( + rxtxstats map[string]*common.RXTXStats = map[string]*common.RXTXStats{} + statsSummaryTemplate *template.Template + statsTemplate *template.Template + + countersEnabledInFramework bool = low.CountersEnabledInFramework + countersEnabledInApplication bool = false + useInterlockedCounters bool = low.UseInterlockedCounters + analyzePacketSizes bool = low.AnalyzePacketSizes +) + +func init() { + statsSummaryTemplate = template.New("summary") + statsSummaryTemplate = template.Must(statsSummaryTemplate.Parse(statsSummaryTemplateText)) + statsTemplate = template.New("node") + statsTemplate = template.Must(statsTemplate.Parse(statsTemplateText)) +} + +func handleRoot(w http.ResponseWriter, r *http.Request) { + url := strings.Split(r.URL.Path, "/") + if len(url) < 2 || url[1] == "" || url[1] == "index.html" { + w.Header().Set("Content-Type", "text/html") + fmt.Fprintf(w, rootText) + } else { + http.Error(w, "Bad root request: "+r.URL.Path, http.StatusBadRequest) + return + } +} + +func handleRXTXStats(w http.ResponseWriter, r *http.Request) { + data := struct { + StatsName string + Values map[string]*common.RXTXStats + }{ + StatsName: "rxtx", + Values: rxtxstats, + } + err := statsSummaryTemplate.Execute(w, &data) + if err != nil { + fmt.Println("Error in RXTX summary stats", err) + } +} + +func handleRXTXStatsNode(w http.ResponseWriter, r *http.Request) { + url := strings.Split(r.URL.Path, "/") + sendNodeVisualization(w, r, "rxtx", url[2], true) +} + +func sendNodeVisualization(w http.ResponseWriter, r *http.Request, statsName, nodeName string, doDropped bool) { + data := struct { + StatsName string + NodeName string + DoDropped bool + }{ + StatsName: statsName, + NodeName: nodeName, + DoDropped: doDropped, + } + err := statsTemplate.Execute(w, &data) + if err != nil { + fmt.Println("Error in", statsName, "node", nodeName, "stats", err) + } +} + +func handleJSONRXTXStats(w http.ResponseWriter, r *http.Request) { + enc := json.NewEncoder(w) + + w.Header().Set("Content-Type", "application/json") + names := make([]string, len(rxtxstats)) + index := 0 + for keys := range rxtxstats { + names[index] = keys + index++ + } + enc.Encode(names) +} + +func handleJSONRXTXStatsNode(w http.ResponseWriter, r *http.Request) { + url := strings.Split(r.URL.Path, "/") + enc := json.NewEncoder(w) + + stats, ok := rxtxstats[url[3]] + if !ok { + http.Error(w, "Bad node name: "+url[3], http.StatusBadRequest) + return + } + w.Header().Set("Content-Type", "application/json") + enc.Encode(stats) +} + +func initCounters(addr *net.TCPAddr) error { + http.HandleFunc("/", handleRoot) + http.HandleFunc("/rxtx/", handleRXTXStatsNode) + http.HandleFunc("/rxtx", handleRXTXStats) + http.HandleFunc("/json/rxtx/", handleJSONRXTXStatsNode) + http.HandleFunc("/json/rxtx", handleJSONRXTXStats) + + server := &http.Server{} + listener, err := net.ListenTCP("tcp", addr) + if err != nil { + return nil + } + + go func() { + if err := server.Serve(listener); err != nil { + common.LogWarning(common.Initialization, "Error while serving HTTP requests:", err) + server.Close() + } + }() + + low.SetCountersEnabledInApplication(true) + countersEnabledInApplication = true + + return nil +} + +func registerRXTXStatitics(s *common.RXTXStats, name string) { + rxtxstats[name] = s +} diff --git a/flow/flow.go b/flow/flow.go index 46add7aa..a5507435 100644 --- a/flow/flow.go +++ b/flow/flow.go @@ -30,6 +30,7 @@ package flow import ( + "net" "os" "runtime" "sync/atomic" @@ -151,6 +152,7 @@ type receiveParameters struct { out low.Rings port *low.Port status []int32 + stats common.RXTXStats } func addReceiver(portId uint16, out low.Rings, inIndexNumber int32) { @@ -158,19 +160,20 @@ func addReceiver(portId uint16, out low.Rings, inIndexNumber int32) { par.port = low.GetPort(portId) par.out = out par.status = make([]int32, maxRecv, maxRecv) - schedState.addFF("receiver", nil, recvRSS, nil, par, nil, receiveRSS, inIndexNumber) + schedState.addFF("receiver", nil, recvRSS, nil, par, nil, receiveRSS, inIndexNumber, &par.stats) } type receiveOSParameters struct { out low.Rings socket int + stats common.RXTXStats } func addOSReceiver(socket int, out low.Rings) { par := new(receiveOSParameters) par.socket = socket par.out = out - schedState.addFF("OS receiver", nil, recvOS, nil, par, nil, sendReceiveKNI, 0) + schedState.addFF("OS receiver", nil, recvOS, nil, par, nil, sendReceiveKNI, 0, &par.stats) } type KNIParameters struct { @@ -180,6 +183,7 @@ type KNIParameters struct { recv bool send bool linuxCore bool + stats common.RXTXStats } func addKNI(portId uint16, recv bool, out low.Rings, send bool, in low.Rings, inIndexNumber int32, name string, core bool) { @@ -191,9 +195,9 @@ func addKNI(portId uint16, recv bool, out low.Rings, send bool, in low.Rings, in par.send = send par.linuxCore = core if core { - schedState.addFF(name, nil, processKNI, nil, par, nil, comboKNI, inIndexNumber) + schedState.addFF(name, nil, processKNI, nil, par, nil, comboKNI, inIndexNumber, &par.stats) } else { - schedState.addFF(name, nil, processKNI, nil, par, nil, sendReceiveKNI, inIndexNumber) + schedState.addFF(name, nil, processKNI, nil, par, nil, sendReceiveKNI, inIndexNumber, &par.stats) } } @@ -204,6 +208,7 @@ type generateParameters struct { mempool *low.Mempool targetChannel chan uint64 targetSpeed float64 + stats common.RXTXStats } func addGenerator(out low.Rings, generateFunction GenerateFunction, context UserContext) { @@ -212,7 +217,7 @@ func addGenerator(out low.Rings, generateFunction GenerateFunction, context User par.generateFunction = generateFunction ctx := make([]UserContext, 1, 1) ctx[0] = context - schedState.addFF("generator", nil, nil, pGenerate, par, &ctx, generate, 0) + schedState.addFF("generator", nil, nil, pGenerate, par, &ctx, generate, 0, &par.stats) } func addFastGenerator(out low.Rings, generateFunction GenerateFunction, @@ -232,7 +237,7 @@ func addFastGenerator(out low.Rings, generateFunction GenerateFunction, par.targetChannel = make(chan uint64, 1) ctx := make([]UserContext, 1, 1) ctx[0] = context - schedState.addFF("fast generator", nil, nil, pFastGenerate, par, &ctx, fastGenerate, 0) + schedState.addFF("fast generator", nil, nil, pFastGenerate, par, &ctx, fastGenerate, 0, &par.stats) return par.targetChannel, nil } @@ -240,6 +245,7 @@ type sendParameters struct { in low.Rings port uint16 anyway bool + stats common.RXTXStats } func addSender(port uint16, in low.Rings, inIndexNumber int32) { @@ -247,19 +253,20 @@ func addSender(port uint16, in low.Rings, inIndexNumber int32) { par.port = port par.in = in par.anyway = schedState.anyway - schedState.addFF("sender", nil, send, nil, par, nil, sendReceiveKNI, inIndexNumber) + schedState.addFF("sender", nil, send, nil, par, nil, sendReceiveKNI, inIndexNumber, &par.stats) } type sendOSParameters struct { in low.Rings socket int + stats common.RXTXStats } func addSenderOS(socket int, in low.Rings, inIndexNumber int32) { par := new(sendOSParameters) par.socket = socket par.in = in - schedState.addFF("sender OS", nil, sendOS, nil, par, nil, sendReceiveKNI, inIndexNumber) + schedState.addFF("sender OS", nil, sendOS, nil, par, nil, sendReceiveKNI, inIndexNumber, &par.stats) } type copyParameters struct { @@ -275,7 +282,7 @@ func addCopier(in low.Rings, out low.Rings, outCopy low.Rings, inIndexNumber int par.out = out par.outCopy = outCopy par.mempool = low.CreateMempool("copy") - schedState.addFF("copy", nil, nil, pcopy, par, nil, segmentCopy, inIndexNumber) + schedState.addFF("copy", nil, nil, pcopy, par, nil, segmentCopy, inIndexNumber, nil) } func makePartitioner(N uint64, M uint64) *Func { @@ -323,19 +330,21 @@ func makeHandler(handleFunction HandleFunction, vectorHandleFunction VectorHandl type writeParameters struct { in low.Rings filename string + stats common.RXTXStats } func addWriter(filename string, in low.Rings, inIndexNumber int32) { par := new(writeParameters) par.in = in par.filename = filename - schedState.addFF("writer", write, nil, nil, par, nil, readWrite, inIndexNumber) + schedState.addFF("write", write, nil, nil, par, nil, readWrite, inIndexNumber, &par.stats) } type readParameters struct { out low.Rings filename string repcount int32 + stats common.RXTXStats } func addReader(filename string, out low.Rings, repcount int32) { @@ -343,7 +352,7 @@ func addReader(filename string, out low.Rings, repcount int32) { par.out = out par.filename = filename par.repcount = repcount - schedState.addFF("reader", read, nil, nil, par, nil, readWrite, 0) + schedState.addFF("read", read, nil, nil, par, nil, readWrite, 0, &par.stats) } func makeSlice(out low.Rings, segment *processSegment) *Func { @@ -372,7 +381,7 @@ func addSegment(in low.Rings, first *Func, inIndexNumber int32) *processSegment segment.contexts = make([](UserContext), 0, 0) par.out = &segment.out par.stype = &segment.stype - schedState.addFF("segment", nil, nil, segmentProcess, par, &segment.contexts, segmentCopy, inIndexNumber) + schedState.addFF("segment", nil, nil, segmentProcess, par, &segment.contexts, segmentCopy, inIndexNumber, nil) return segment } @@ -416,6 +425,7 @@ func SetUseHWCapability(capa HWCapability, use bool) { // At i40e drivers burstSize should be >= 4 // http://mails.dpdk.org/archives/dev/2016-December/052554.html const burstSize = 32 + // Size of all vectors in system. Can't be changed due to asm stickiness // Using vector functions with vBurstSize != burstSize is undefined behaviour const vBurstSize = 32 @@ -494,6 +504,24 @@ type Config struct { // should be reinit every receving or generating a packet. This can be removed if // EncapsulateHead and DecapsulateHead are not in use NoPacketHeadChange bool + // HTTP server address to use for serving statistics and + // telemetry. Server provides different types of statistics which + // can be controlled by statistics flags. File format is + // JSON. Registered roots return statistics for all framework + // graph nodes or accept an optional argument /ID where ID is port + // number for send and receive nodes. + // + // Following are possible statistics requests: + // + // /rxtxstats for protocol statistics gathered on all send and + // receive or /rxtxstats/name for individual send/receiver node. + // + // /telemetry for all nodes names and their counters which include + // received, send, processed, lost and dropped packets. Using + // /telemetry/name returns information about individual node. + // + // If no string is specified, no HTTP server is spawned. + StatsHTTPAddress *net.TCPAddr } // SystemInit is initialization of system. This function should be always called before graph construction. @@ -607,11 +635,23 @@ func SystemInit(args *Config) error { devices = make(map[string]int) // Init scheduler common.LogTitle(common.Initialization, "------------***------ Initializing scheduler -----***------------") - StopRing := low.CreateRings(burstSize*sizeMultiplier, maxInIndex) + StopRing := low.CreateRings(burstSize*sizeMultiplier, maxInIndex /* Maximum possible rings */) common.LogDebug(common.Initialization, "Scheduler can use cores:", cpus) schedState = newScheduler(cpus, schedulerOff, schedulerOffRemove, stopDedicatedCore, StopRing, checkTime, debugTime, maxPacketsToClone, maxRecv, anyway) - // Init packet processing + + // Set HW offloading flag in packet package packet.SetHWTXChecksumFlag(hwtxchecksum) + + // Initialize telemetry web server + if countersEnabledInFramework { + if args.StatsHTTPAddress != nil { + if err = initCounters(args.StatsHTTPAddress); err != nil { + return err + } + } + } + + // Init packet processing for i := 0; i < 10; i++ { for j := 0; j < burstSize; j++ { vEach[i][j] = uint8(i) @@ -1256,6 +1296,7 @@ func segmentProcess(parameters interface{}, inIndex []int32, stopper [2]chan int currentState.ZeroAttempts[q-1]++ continue } + if scalar { // Scalar code for i := uint(0); i < n; i++ { currentFunc := firstFunc @@ -1336,12 +1377,12 @@ func recvRSS(parameters interface{}, inIndex []int32, flag *int32, coreID int) { i-- } } - low.ReceiveRSS(uint16(srp.port.PortId), inIndex, srp.out, flag, coreID, &srp.status[index]) + low.ReceiveRSS(uint16(srp.port.PortId), inIndex, srp.out, flag, coreID, &srp.status[index], &srp.stats) } func recvOS(parameters interface{}, inIndex []int32, flag *int32, coreID int) { srp := parameters.(*receiveOSParameters) - low.ReceiveOS(srp.socket, srp.out[0], flag, coreID) + low.ReceiveOS(srp.socket, srp.out[0], flag, coreID, &srp.stats) } func processKNI(parameters interface{}, inIndex []int32, flag *int32, coreID int) { @@ -1349,7 +1390,7 @@ func processKNI(parameters interface{}, inIndex []int32, flag *int32, coreID int if srk.linuxCore == true { coreID = schedState.cores[createdPorts[srk.port.PortId].KNICoreIndex].id } - low.SrKNI(uint16(srk.port.PortId), flag, coreID, srk.recv, srk.out, srk.send, srk.in) + low.SrKNI(uint16(srk.port.PortId), flag, coreID, srk.recv, srk.out, srk.send, srk.in, &srk.stats) } func pGenerate(parameters interface{}, inIndex []int32, stopper [2]chan int, report chan reportPair, context []UserContext) { @@ -1374,6 +1415,10 @@ func pGenerate(parameters interface{}, inIndex []int32, stopper [2]chan int, rep } generateFunction(tempPacket, context[0]) safeEnqueueOne(OUT[0], tempPacket.ToUintptr()) + + if countersEnabledInApplication { + updatePortStatsOne(&gp.stats, tempPacket) + } } } } @@ -1421,7 +1466,7 @@ func pFastGenerate(parameters interface{}, inIndex []int32, stopper [2]chan int, } if vector == false { for i := range bufs { - // TODO Maybe we need to prefetcht here? + // TODO Maybe we need to prefetch here? tempPacket = packet.ExtractPacket(bufs[i]) generateFunction(tempPacket, context[0]) if reportMbits { @@ -1434,6 +1479,9 @@ func pFastGenerate(parameters interface{}, inIndex []int32, stopper [2]chan int, } safeEnqueue(OUT[0], bufs, burstSize) currentState.V.Packets += uint64(burstSize) + if countersEnabledInApplication { + updatePortStats(&gp.stats, bufs, burstSize) + } // GO parks goroutines while Sleep. So Sleep lasts more time than our precision // we just want to slow goroutine down without parking, so loop is OK for this. // time.Now lasts approximately 70ns and this satisfies us @@ -1483,12 +1531,13 @@ func pcopy(parameters interface{}, inIndex []int32, stopper [2]chan int, report default: for q := int32(1); q < inIndex[0]+1; q++ { n := IN[inIndex[q]].DequeueBurst(bufs1, burstSize) + if n != 0 { if err := low.AllocateMbufs(bufs2, mempool, n); err != nil { common.LogFatal(common.Debug, err) } for i := uint(0); i < n; i++ { - // TODO Maybe we need to prefetcht here? + // TODO Maybe we need to prefetch here? tempPacket1 = packet.ExtractPacket(bufs1[i]) tempPacket2 = packet.ExtractPacket(bufs2[i]) packet.GeneratePacketFromByte(tempPacket2, tempPacket1.GetRawPacketBytes()) @@ -1517,12 +1566,12 @@ func pcopy(parameters interface{}, inIndex []int32, stopper [2]chan int, report func send(parameters interface{}, inIndex []int32, flag *int32, coreID int) { srp := parameters.(*sendParameters) - low.Send(srp.port, srp.in, srp.anyway, flag, coreID) + low.Send(srp.port, srp.in, srp.anyway, flag, coreID, &srp.stats) } func sendOS(parameters interface{}, inIndex []int32, flag *int32, coreID int) { srp := parameters.(*sendOSParameters) - low.SendOS(srp.socket, srp.in, flag, coreID) + low.SendOS(srp.socket, srp.in, flag, coreID, &srp.stats) } func merge(from low.Rings, to low.Rings) { @@ -1655,6 +1704,11 @@ func write(parameters interface{}, inIndex []int32, stopper [2]chan int) { default: for q := int32(0); q < inIndex[0]; q++ { n := IN[q].DequeueBurst(bufIn, 1) + + if countersEnabledInApplication { + updatePortStats(&wp.stats, bufIn, n) + } + if n == 0 { continue } @@ -1721,6 +1775,10 @@ func read(parameters interface{}, inIndex []int32, stopper [2]chan int) { // TODO we need packet reassembly here. However we don't // use mbuf packet_type here, so it is impossible. safeEnqueueOne(OUT[0], tempPacket.ToUintptr()) + + if countersEnabledInApplication { + updatePortStatsOne(&rp.stats, tempPacket) + } } } } @@ -1846,3 +1904,40 @@ func CheckFatal(err error) { common.LogFatalf(common.No, "failed with message: %s\n", err.Error()) } } + +func updatePortStatsOne(stats *common.RXTXStats, pkt *packet.Packet) { + if useInterlockedCounters { + atomic.AddUint64(&stats.PacketsProcessed, 1) + if analyzePacketSizes { + atomic.AddUint64(&stats.BytesProcessed, uint64(pkt.GetPacketLen())) + } + } else { + stats.PacketsProcessed++ + if analyzePacketSizes { + stats.BytesProcessed += uint64(pkt.GetPacketLen()) + } + } +} + +func updatePortStats(stats *common.RXTXStats, packetPtrs []uintptr, number uint) { + if useInterlockedCounters { + atomic.AddUint64(&stats.PacketsProcessed, uint64(number)) + if analyzePacketSizes { + atomic.AddUint64(&stats.BytesProcessed, calculateSize(packetPtrs, number)) + } + } else { + stats.PacketsProcessed += uint64(number) + if analyzePacketSizes { + stats.BytesProcessed += calculateSize(packetPtrs, number) + } + } +} + +func calculateSize(packetPtrs []uintptr, number uint) uint64 { + size := uint64(0) + for i := uint(0); i < number; i++ { + tempPacket := packet.ExtractPacket(packetPtrs[i]) + size += uint64(tempPacket.GetPacketLen()) + } + return size +} diff --git a/flow/scheduler.go b/flow/scheduler.go index 80365305..50382311 100644 --- a/flow/scheduler.go +++ b/flow/scheduler.go @@ -128,14 +128,14 @@ type flowFunction struct { // Adding every flow function to scheduler list func (scheduler *scheduler) addFF(name string, ucfn uncloneFlowFunction, Cfn cFlowFunction, cfn cloneFlowFunction, - par interface{}, context *[]UserContext, fType ffType, inIndexNumber int32) { + par interface{}, context *[]UserContext, fType ffType, inIndexNumber int32, rxtxstats *common.RXTXStats) { ff := new(flowFunction) nameC := 1 - tName := name + tName := name + strconv.Itoa(nameC) for i := range scheduler.ff { if scheduler.ff[i].name == tName { - tName = name + strconv.Itoa(nameC) nameC++ + tName = name + strconv.Itoa(nameC) } } ff.name = tName @@ -150,6 +150,9 @@ func (scheduler *scheduler) addFF(name string, ucfn uncloneFlowFunction, Cfn cFl scheduler.maxInIndex = inIndexNumber } scheduler.ff = append(scheduler.ff, ff) + if countersEnabledInFramework && rxtxstats != nil { + registerRXTXStatitics(rxtxstats, tName) + } } type scheduler struct { @@ -221,8 +224,13 @@ func (scheduler *scheduler) systemStart() (err error) { } else { common.LogDebug(common.Initialization, "Start STOP at scheduler", core, "core") } + var stopstats *common.RXTXStats + if countersEnabledInFramework { + stopstats = new(common.RXTXStats) + registerRXTXStatitics(stopstats, "systemstop") + } go func() { - low.Stop(scheduler.StopRing, &scheduler.stopFlag, core) + low.Stop(scheduler.StopRing, &scheduler.stopFlag, core, stopstats) }() for i := range scheduler.ff { if err = scheduler.ff[i].startNewInstance(constructNewIndex(scheduler.ff[i].inIndexNumber), scheduler); err != nil { diff --git a/low/low.go b/low/low.go index 2dfd89af..e8e5748a 100644 --- a/low/low.go +++ b/low/low.go @@ -31,6 +31,12 @@ import ( "github.com/intel-go/nff-go/types" ) +var ( + CountersEnabledInFramework bool = bool(C.counters_enabled_in_framework) + UseInterlockedCounters bool = bool(C.use_interlocked_counters) + AnalyzePacketSizes bool = bool(C.analyze_packet_sizes) +) + var ringName = 1 // DirectStop frees mbufs. @@ -490,15 +496,15 @@ func (ring *Ring) GetRingCount() uint32 { } // ReceiveRSS - get packets from port and enqueue on a Ring. -func ReceiveRSS(port uint16, inIndex []int32, OUT Rings, flag *int32, coreID int, race *int32) { +func ReceiveRSS(port uint16, inIndex []int32, OUT Rings, flag *int32, coreID int, race *int32, stats *common.RXTXStats) { if C.rte_eth_dev_socket_id(C.uint16_t(port)) != C.int(C.rte_lcore_to_socket_id(C.uint(coreID))) { common.LogWarning(common.Initialization, "Receive port", port, "is on remote NUMA node to polling thread - not optimal performance.") } C.receiveRSS(C.uint16_t(port), (*C.int32_t)(unsafe.Pointer(&(inIndex[0]))), C.extractDPDKRings((**C.struct_nff_go_ring)(unsafe.Pointer(&(OUT[0]))), C.int32_t(len(OUT))), - (*C.int)(unsafe.Pointer(flag)), C.int(coreID), (*C.int)(unsafe.Pointer(race))) + (*C.int)(unsafe.Pointer(flag)), C.int(coreID), (*C.int)(unsafe.Pointer(race)), (*C.RXTXStats)(unsafe.Pointer(stats))) } -func SrKNI(port uint16, flag *int32, coreID int, recv bool, OUT Rings, send bool, IN Rings) { +func SrKNI(port uint16, flag *int32, coreID int, recv bool, OUT Rings, send bool, IN Rings, stats *common.RXTXStats) { var nOut *C.struct_rte_ring var nIn **C.struct_rte_ring if OUT != nil { @@ -508,20 +514,21 @@ func SrKNI(port uint16, flag *int32, coreID int, recv bool, OUT Rings, send bool nIn = C.extractDPDKRings((**C.struct_nff_go_ring)(unsafe.Pointer(&(IN[0]))), C.int32_t(len(IN))) } C.nff_go_KNI(C.uint16_t(port), (*C.int)(unsafe.Pointer(flag)), C.int(coreID), - C.bool(recv), nOut, C.bool(send), nIn, C.int32_t(len(IN))) + C.bool(recv), nOut, C.bool(send), nIn, C.int32_t(len(IN)), (*C.RXTXStats)(unsafe.Pointer(stats))) } // Send - dequeue packets and send. -func Send(port uint16, IN Rings, anyway bool, flag *int32, coreID int) { +func Send(port uint16, IN Rings, anyway bool, flag *int32, coreID int, stats *common.RXTXStats) { if C.rte_eth_dev_socket_id(C.uint16_t(port)) != C.int(C.rte_lcore_to_socket_id(C.uint(coreID))) { common.LogWarning(common.Initialization, "Send port", port, "is on remote NUMA node to polling thread - not optimal performance.") } - C.nff_go_send(C.uint16_t(port), C.extractDPDKRings((**C.struct_nff_go_ring)(unsafe.Pointer(&(IN[0]))), C.int32_t(len(IN))), C.int32_t(len(IN)), C.bool(anyway), (*C.int)(unsafe.Pointer(flag)), C.int(coreID)) + C.nff_go_send(C.uint16_t(port), C.extractDPDKRings((**C.struct_nff_go_ring)(unsafe.Pointer(&(IN[0]))), C.int32_t(len(IN))), C.int32_t(len(IN)), + C.bool(anyway), (*C.int)(unsafe.Pointer(flag)), C.int(coreID), (*C.RXTXStats)(unsafe.Pointer(stats))) } // Stop - dequeue and free packets. -func Stop(IN Rings, flag *int32, coreID int) { - C.nff_go_stop(C.extractDPDKRings((**C.struct_nff_go_ring)(unsafe.Pointer(&(IN[0]))), C.int32_t(len(IN))), C.int(len(IN)), (*C.int)(unsafe.Pointer(flag)), C.int(coreID)) +func Stop(IN Rings, flag *int32, coreID int, stats *common.RXTXStats) { + C.nff_go_stop(C.extractDPDKRings((**C.struct_nff_go_ring)(unsafe.Pointer(&(IN[0]))), C.int32_t(len(IN))), C.int(len(IN)), (*C.int)(unsafe.Pointer(flag)), C.int(coreID), (*C.RXTXStats)(unsafe.Pointer(stats))) } // InitDPDKArguments allocates and initializes arguments for dpdk. @@ -745,15 +752,22 @@ func CheckHWTXChecksumCapability(port uint16) bool { return bool(C.check_hwtxchecksum_capability(C.uint16_t(port))) } -func ReceiveOS(socket int, OUT *Ring, flag *int32, coreID int) { +func ReceiveOS(socket int, OUT *Ring, flag *int32, coreID int, stats *common.RXTXStats) { m := CreateMempool("receiveOS") - C.receiveOS(C.int(socket), OUT.DPDK_ring, (*C.struct_rte_mempool)(unsafe.Pointer(m)), (*C.int)(unsafe.Pointer(flag)), C.int(coreID)) + C.receiveOS(C.int(socket), OUT.DPDK_ring, (*C.struct_rte_mempool)(unsafe.Pointer(m)), + (*C.int)(unsafe.Pointer(flag)), C.int(coreID), (*C.RXTXStats)(unsafe.Pointer(stats))) } -func SendOS(socket int, IN Rings, flag *int32, coreID int) { - C.sendOS(C.int(socket), C.extractDPDKRings((**C.struct_nff_go_ring)(unsafe.Pointer(&(IN[0]))), C.int32_t(len(IN))), C.int32_t(len(IN)), (*C.int)(unsafe.Pointer(flag)), C.int(coreID)) +func SendOS(socket int, IN Rings, flag *int32, coreID int, stats *common.RXTXStats) { + C.sendOS(C.int(socket), C.extractDPDKRings((**C.struct_nff_go_ring)(unsafe.Pointer(&(IN[0]))), + C.int32_t(len(IN))), C.int32_t(len(IN)), (*C.int)(unsafe.Pointer(flag)), C.int(coreID), + (*C.RXTXStats)(unsafe.Pointer(stats))) } func InitDevice(device string) int { return int(C.initDevice(C.CString(device))) } + +func SetCountersEnabledInApplication(enabled bool) { + C.counters_enabled_in_application = C.bool(true) +} diff --git a/low/low.h b/low/low.h index 7b4f5810..9f08ee98 100644 --- a/low/low.h +++ b/low/low.h @@ -45,6 +45,9 @@ // #define DEBUG // #define REASSEMBLY +#define COUNTERS_ENABLED +#define USE_INTERLOCKED_COUNTERS +#define ANALYZE_PACKETS_SIZES #define recvNotUsed 0 #define recvDone 2 @@ -83,10 +86,67 @@ struct rte_ip_frag_death_row* pdeath_row = NULL; #endif +#ifdef COUNTERS_ENABLED +#ifdef USE_INTERLOCKED_COUNTERS +#define UPDATE_PACKETS(packets, dropped) \ + __sync_fetch_and_add(&stats->PacketsProcessed, (packets)); \ + __sync_fetch_and_add(&stats->PacketsDropped, (dropped)); +#ifdef ANALYZE_PACKETS_SIZES +#define UPDATE_BYTES(bytes) \ + __sync_fetch_and_add(&stats->BytesProcessed, (bytes)); +#else // ANALYZE_PACKETS_SIZES +#define UPDATE_BYTES(bytes) \ + do {} while (0) +#endif // ANALYZE_PACKETS_SIZES +#else // USE_INTERLOCKED_COUNTERS +#define UPDATE_PACKETS(packets, dropped) \ + stats->PacketsProcessed += (packets); \ + stats->PacketsDropped += (dropped); +#ifdef ANALYZE_PACKETS_SIZES +#define UPDATE_BYTES(bytes) \ + stats->BytesProcessed += (bytes); +#else // ANALYZE_PACKETS_SIZES +#define UPDATE_BYTES(bytes) \ + do {} while (0) +#endif // ANALYZE_PACKETS_SIZES +#endif // USE_INTERLOCKED_COUNTERS +#define UPDATE_COUNTERS(packets, bytes, dropped) \ + if (counters_enabled_in_application) { \ + UPDATE_PACKETS(packets, dropped) \ + UPDATE_BYTES(bytes) \ + } +#else // COUNTERS_ENABLED +#define UPDATE_COUNTERS(packets, bytes, dropped) \ + do {} while (0) +#endif // COUNTERS_ENABLED + +#ifdef COUNTERS_ENABLED +bool counters_enabled_in_framework = true; +bool counters_enabled_in_application = false; +#else +bool counters_enabled_in_framework = false; +#endif + +#ifdef USE_INTERLOCKED_COUNTERS +bool use_interlocked_counters = true; +#else +bool use_interlocked_counters = false; +#endif + +#ifdef ANALYZE_PACKETS_SIZES +bool analyze_packet_sizes = true; +#else +bool analyze_packet_sizes = false; +#endif + long receive_received = 0, receive_pushed = 0; long send_required = 0, send_sent = 0; long stop_freed = 0; +typedef struct { + uint64_t PacketsProcessed, PacketsDropped, BytesProcessed; +} RXTXStats; + int mbufStructSize; int headroomSize; int defaultStart; @@ -269,6 +329,17 @@ int port_init(uint16_t port, bool willReceive, struct rte_mempool **mbuf_pools, return 0; } +#if defined(COUNTERS_ENABLED) && defined(ANALYZE_PACKETS_SIZES) +__attribute__((always_inline)) +static inline uint64_t calculateSize(struct rte_mbuf *bufs[BURST_SIZE], uint16_t number) { + uint64_t size = 0; + for (uint32_t i = 0; i < number; i++) { + size += bufs[i]->pkt_len; + } + return size; +} +#endif + __attribute__((always_inline)) static inline void handleUnpushed(struct rte_mbuf *bufs[BURST_SIZE], uint16_t real_number, uint16_t required_number) { if (unlikely(real_number < required_number)) { @@ -363,7 +434,7 @@ static inline struct rte_mbuf* reassemble(struct rte_ip_frag_tbl* tbl, struct rt return buf; } -void receiveRSS(uint16_t port, volatile int32_t *inIndex, struct rte_ring **out_rings, volatile int *flag, int coreId, volatile int *race) { +void receiveRSS(uint16_t port, volatile int32_t *inIndex, struct rte_ring **out_rings, volatile int *flag, int coreId, volatile int *race, RXTXStats *stats) { setAffinity(coreId); struct rte_mbuf *bufs[BURST_SIZE]; REASSEMBLY_INIT @@ -378,12 +449,15 @@ void receiveRSS(uint16_t port, volatile int32_t *inIndex, struct rte_ring **out_ rx_pkts_number = handleReceived(bufs, rx_pkts_number, tbl, pdeath_row); uint16_t pushed_pkts_number = rte_ring_enqueue_burst(out_rings[inIndex[q+1]], (void*)bufs, rx_pkts_number, NULL); + + UPDATE_COUNTERS(pushed_pkts_number, calculateSize(bufs, pushed_pkts_number), rx_pkts_number - pushed_pkts_number); + // Free any packets which can't be pushed to the ring. The ring is probably full. handleUnpushed((void*)bufs, pushed_pkts_number, rx_pkts_number); #ifdef DEBUG receive_received += rx_pkts_number; receive_pushed += pushed_pkts_number; -#endif +#endif // DEBUG } } free(out_rings); @@ -392,8 +466,8 @@ void receiveRSS(uint16_t port, volatile int32_t *inIndex, struct rte_ring **out_ } void nff_go_KNI(uint16_t port, volatile int *flag, int coreId, - bool recv, struct rte_ring *out_ring, - bool send, struct rte_ring **in_rings, int32_t inIndexNumber) { + bool recv, struct rte_ring *out_ring, + bool send, struct rte_ring **in_rings, int32_t inIndexNumber, RXTXStats *stats) { setAffinity(coreId); struct rte_mbuf *bufs[BURST_SIZE]; int q = 0; @@ -406,6 +480,9 @@ void nff_go_KNI(uint16_t port, volatile int *flag, int coreId, if (likely(rx_pkts_number != 0)) { rx_pkts_number = handleReceived(bufs, rx_pkts_number, tbl, pdeath_row); uint16_t pushed_pkts_number = rte_ring_enqueue_burst(out_ring, (void*)bufs, rx_pkts_number, NULL); + + UPDATE_COUNTERS(pushed_pkts_number, calculateSize(bufs, pushed_pkts_number), rx_pkts_number - pushed_pkts_number); + // Free any packets which can't be pushed to the ring. The ring is probably full. handleUnpushed(bufs, pushed_pkts_number, rx_pkts_number); } @@ -416,6 +493,9 @@ void nff_go_KNI(uint16_t port, volatile int *flag, int coreId, uint16_t pkts_for_tx_number = rte_ring_mc_dequeue_burst(in_rings[q], (void*)bufs, BURST_SIZE, NULL); if (likely(pkts_for_tx_number != 0)) { uint16_t tx_pkts_number = rte_kni_tx_burst(kni[port], bufs, pkts_for_tx_number); + + UPDATE_COUNTERS(tx_pkts_number, calculateSize(bufs, tx_pkts_number), pkts_for_tx_number - tx_pkts_number); + // Free any unsent packets handleUnpushed(bufs, tx_pkts_number, pkts_for_tx_number); } @@ -427,7 +507,7 @@ void nff_go_KNI(uint16_t port, volatile int *flag, int coreId, *flag = wasStopped; } -void nff_go_send(uint16_t port, struct rte_ring **in_rings, int32_t inIndexNumber, bool anyway, volatile int *flag, int coreId) { +void nff_go_send(uint16_t port, struct rte_ring **in_rings, int32_t inIndexNumber, bool anyway, volatile int *flag, int coreId, RXTXStats *stats) { setAffinity(coreId); struct rte_mbuf *bufs[BURST_SIZE]; @@ -449,6 +529,9 @@ void nff_go_send(uint16_t port, struct rte_ring **in_rings, int32_t inIndexNumbe if (switchQueue) { queue = !queue; } + + UPDATE_COUNTERS(tx_pkts_number, calculateSize(bufs, tx_pkts_number), pkts_for_tx_number - tx_pkts_number); + // Free any unsent packets handleUnpushed(bufs, tx_pkts_number, pkts_for_tx_number); #ifdef DEBUG @@ -461,7 +544,7 @@ void nff_go_send(uint16_t port, struct rte_ring **in_rings, int32_t inIndexNumbe *flag = wasStopped; } -void nff_go_stop(struct rte_ring **in_rings, int len, volatile int *flag, int coreId) { +void nff_go_stop(struct rte_ring **in_rings, int len, volatile int *flag, int coreId, RXTXStats *stats) { setAffinity(coreId); struct rte_mbuf *bufs[BURST_SIZE]; uint16_t buf; @@ -475,6 +558,8 @@ void nff_go_stop(struct rte_ring **in_rings, int len, volatile int *flag, int co if (unlikely(pkts_for_free_number == 0)) continue; + UPDATE_COUNTERS(pkts_for_free_number, calculateSize(bufs, pkts_for_free_number), 0); + // Free all these packets for (buf = 0; buf < pkts_for_free_number; buf++) { rte_pktmbuf_free(bufs[buf]); @@ -559,6 +644,21 @@ int eal_init(int argc, char *argv[], uint32_t burstSize, int32_t needKNI, bool n return 0; } +int allocateMbufs(struct rte_mempool *mempool, struct rte_mbuf **bufs, unsigned count) { + int ret = rte_pktmbuf_alloc_bulk(mempool, bufs, count); + if (ret == 0) { + for (int i = 0; i < count; i++) { + if (L2CanBeChanged == true) { + mbufInitL2(bufs[i]); + } +#ifdef REASSEMBLY + mbufInitNextChain(bufs[i]); +#endif + } + } + return ret; +} + struct rte_mempool * createMempool(uint32_t num_mbufs, uint32_t mbuf_cache_size) { struct rte_mempool *mbuf_pool; @@ -590,21 +690,6 @@ struct rte_mempool * createMempool(uint32_t num_mbufs, uint32_t mbuf_cache_size) return mbuf_pool; } -int allocateMbufs(struct rte_mempool *mempool, struct rte_mbuf **bufs, unsigned count) { - int ret = rte_pktmbuf_alloc_bulk(mempool, bufs, count); - if (ret == 0) { - for (int i = 0; i < count; i++) { - if (L2CanBeChanged == true) { - mbufInitL2(bufs[i]); - } -#ifdef REASSEMBLY - mbufInitNextChain(bufs[i]); -#endif - } - } - return ret; -} - int getMempoolSpace(struct rte_mempool * m) { return rte_mempool_in_use_count(m); } @@ -736,7 +821,7 @@ int initDevice(char *name) { return s; } -void receiveOS(int socket, struct rte_ring *out_ring, struct rte_mempool *m, volatile int *flag, int coreId) { +void receiveOS(int socket, struct rte_ring *out_ring, struct rte_mempool *m, volatile int *flag, int coreId, RXTXStats *stats) { setAffinity(coreId); const int recvOSBusrst = BURST_SIZE; struct rte_mbuf *bufs[recvOSBusrst]; @@ -756,13 +841,16 @@ void receiveOS(int socket, struct rte_ring *out_ring, struct rte_mempool *m, vol } uint16_t rx_pkts_number = handleReceived(bufs, recvOSBusrst, tbl, pdeath_row); uint16_t pushed_pkts_number = rte_ring_enqueue_burst(out_ring, (void*)bufs, rx_pkts_number, NULL); - // Free any packets which can't be pushed to the ring. The ring is probably full. - handleUnpushed((void*)bufs, pushed_pkts_number, rx_pkts_number); + + UPDATE_COUNTERS(pushed_pkts_number, calculateSize(bufs, pushed_pkts_number), rx_pkts_number - pushed_pkts_number); + + // Free any packets which can't be pushed to the ring. The ring is probably full. + handleUnpushed((void*)bufs, pushed_pkts_number, rx_pkts_number); } *flag = wasStopped; } -void sendOS(int socket, struct rte_ring **in_rings, int32_t inIndexNumber, volatile int *flag, int coreId) { +void sendOS(int socket, struct rte_ring **in_rings, int32_t inIndexNumber, volatile int *flag, int coreId, RXTXStats *stats) { setAffinity(coreId); struct rte_mbuf *bufs[BURST_SIZE]; @@ -776,6 +864,9 @@ void sendOS(int socket, struct rte_ring **in_rings, int32_t inIndexNumber, volat for (int i = 0; i < pkts_for_tx_number; i++) { send(socket, (char *)(bufs[i]) + defaultStart, rte_pktmbuf_pkt_len(bufs[i]), 0); } + + UPDATE_COUNTERS(pkts_for_tx_number, calculateSize(bufs, pkts_for_tx_number), 0); + // Free all packets handleUnpushed(bufs, 0, pkts_for_tx_number); } From 737929879bd30b3cdab6684a8e3924317994aaef Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Thu, 7 Mar 2019 08:15:14 -0600 Subject: [PATCH 22/24] Updated pktgen to version 3.6.5 to fix bug #526 --- dpdk/pktgen-dpdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 7a615b28bcbf0993d3005daa68290f7482204804 Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Wed, 6 Mar 2019 13:16:08 -0800 Subject: [PATCH 23/24] Implemented #382 to repeat failed tests several times --- test/framework/main/tf.go | 3 ++- test/framework/testsuite.go | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/test/framework/main/tf.go b/test/framework/main/tf.go index 873454fc..25a8b70d 100644 --- a/test/framework/main/tf.go +++ b/test/framework/main/tf.go @@ -28,6 +28,7 @@ func main() { flag.StringVar(&configFile, "config", "config.json", "Name of config file to use") flag.StringVar(&directory, "directory", "", "Use `directory` to output log files instead of timestamp") flag.BoolVar(&test.NoDeleteContainersOnExit, "nodelete", false, "Do not remove containers after tests finish") + repeatFailed := flag.Int("repeat-failed", 1, "Number of times to repeat a test which failed. This includes tests that timed out.") flag.Parse() // Read config @@ -46,6 +47,6 @@ func main() { } // Start test execution - status := config.RunAllTests(directory, tl) + status := config.RunAllTests(directory, tl, *repeatFailed) os.Exit(status) } diff --git a/test/framework/testsuite.go b/test/framework/testsuite.go index c5a8cc7a..e066f8d3 100644 --- a/test/framework/testsuite.go +++ b/test/framework/testsuite.go @@ -223,7 +223,7 @@ func isTestInList(test *TestConfig, tl TestsList) bool { } // RunAllTests launches all tests. -func (config *TestsuiteConfig) RunAllTests(logdir string, tl TestsList) int { +func (config *TestsuiteConfig) RunAllTests(logdir string, tl TestsList, repeatCount int) int { report := StartReport(logdir) if report == nil { return 255 @@ -233,19 +233,38 @@ func (config *TestsuiteConfig) RunAllTests(logdir string, tl TestsList) int { sichan := make(chan os.Signal, 1) signal.Notify(sichan, os.Interrupt) - var totalTests, passedTests, failedTests []string + type TestInfo struct { + TestName string + Repeated int + } + + var totalTests, passedTests, failedTests []TestInfo + for iii := range config.Tests { test := &config.Tests[iii] if isTestInList(test, tl) { - tr := config.executeOneTest(test, logdir, sichan) + var tr *TestcaseReportInfo + ti := TestInfo{ + TestName: test.Name, + Repeated: 0, + } + + for ti.Repeated < repeatCount { + tr = config.executeOneTest(test, logdir, sichan) + ti.Repeated++ + if tr.Status == TestReportedPassed || tr.Status == TestInterrupted { + break + } + } + report.AddTestResult(tr) - totalTests = append(totalTests, test.Name) + totalTests = append(totalTests, ti) if tr.Status == TestReportedPassed { - passedTests = append(passedTests, test.Name) + passedTests = append(passedTests, ti) } else { - failedTests = append(failedTests, test.Name) + failedTests = append(failedTests, ti) } if tr.Status == TestInterrupted { @@ -256,9 +275,9 @@ func (config *TestsuiteConfig) RunAllTests(logdir string, tl TestsList) int { report.FinishReport() - LogInfo("EXECUTED TEST NAMES:", totalTests) - LogInfo("PASSED TEST NAMES:", passedTests) - LogInfo("FAILED TEST NAMES:", failedTests) + LogInfo("EXECUTED TEST NAMES AND REPEAT COUNT:", totalTests) + LogInfo("PASSED TEST NAMES AND REPEAT COUNT:", passedTests) + LogInfo("FAILED TEST NAMES AND REPEAT COUNT:", failedTests) LogInfo("TESTS EXECUTED:", len(totalTests)) LogInfo("PASSED:", len(passedTests)) LogInfo("FAILED:", len(failedTests)) From c0347a0049b10ecff8b284e6c7523e26f02db082 Mon Sep 17 00:00:00 2001 From: Gregory Shimansky Date: Thu, 7 Mar 2019 10:04:53 -0600 Subject: [PATCH 24/24] Added substring filter and comparison threshold to report compare --- test/framework/main/report_compare.go | 153 ++++++++++++++++---------- 1 file changed, 96 insertions(+), 57 deletions(-) diff --git a/test/framework/main/report_compare.go b/test/framework/main/report_compare.go index 364af5cc..0cdb7b52 100644 --- a/test/framework/main/report_compare.go +++ b/test/framework/main/report_compare.go @@ -18,11 +18,21 @@ import ( ) var ( - user = "" - password = "" + user = "" + password = "" + substringFilter = "" ) -type inputReportsArray []*test.TestsuiteReport +type inputReport struct { + report *test.TestsuiteReport + fileName string +} + +func (ir *inputReport) String() string { + return ir.report.Timestamp + "(" + ir.fileName + ")" +} + +type inputReportsArray []inputReport func (ira *inputReportsArray) String() string { return fmt.Sprint(*ira) @@ -66,18 +76,18 @@ func (ira *inputReportsArray) Set(value string) error { } else if report.Timestamp == "" { return fmt.Errorf("Bad report from %s contains no timestamp string", value) } - *ira = append(*ira, &report) + *ira = append(*ira, inputReport{&report, value}) return nil } type reportProcessorResult interface { // compare returns true if this report is better than another report - compare(another reportProcessorResult) (bool, error) + compare(another reportProcessorResult, threshold float64) (bool, error) String() string } type reportProcessor interface { - process(*test.TestsuiteReport, bool) reportProcessorResult + process(*inputReport, bool) reportProcessorResult } type comparisonMode struct { @@ -148,6 +158,11 @@ error if any of new reports is worse than base report. `) flag.StringVar(&user, "u", "", "User name to authenticate with for HTTP(S) connection") flag.StringVar(&password, "p", "", "Password to authenticate with for HTTP(S) connection") + flag.StringVar(&substringFilter, "s", "", "Substring filter for test names, e.g. \"-s _off_\".") + threshold := flag.Float64("t", 5.0, `Threshold in percents by which +values in new report may be below values in original report. +E.g. "-t 5" specifies threshold of 5%. If new report value +shows -5% or below, it is considered worse than original.`) verbose := flag.Bool("v", false, "Verbose mode") flag.Parse() @@ -158,22 +173,25 @@ error if any of new reports is worse than base report. values := make([]reportProcessorResult, len(reports)) for iii := range reports { - values[iii] = processMode.process(reports[iii], *verbose) - fmt.Printf("Test report from %s: %s\n", reports[iii].Timestamp, values[iii].String()) + values[iii] = processMode.process(&reports[iii], *verbose) + fmt.Printf("Test report %s: %s\n", reports[iii].String(), values[iii].String()) } fmt.Printf("\n") exitCode := 0 for iii := 1; iii < len(reports); iii++ { - result, err := values[0].compare(values[iii]) + result, err := values[0].compare(values[iii], *threshold) if err != nil { fmt.Print(err) exitCode = 1 break } else if result { - fmt.Printf("New report %s is worse than base report %s\n", - reports[iii].Timestamp, reports[0].Timestamp) + fmt.Printf("With threshold %.2f%% new report %s is WORSE than base report %s.\n", + *threshold, reports[iii].String(), reports[0].String()) exitCode = 1 + } else { + fmt.Printf("With threshold %.2f%% new report %s is OK compared to base report %s.\n", + *threshold, reports[iii].String(), reports[0].String()) } } os.Exit(exitCode) @@ -181,6 +199,7 @@ error if any of new reports is worse than base report. type geomeanProcessorResult struct { reportProcessorResult + report *inputReport geomeanPkts, geomeanMbits, geomeanCores float64 } @@ -198,32 +217,42 @@ type geomeanProcessorResultMbits struct { } // compare by average packets received to ensure transitivity -func (gp geomeanProcessorResultPkts) compare(another reportProcessorResult) (bool, error) { +func (gp geomeanProcessorResultPkts) compare(another reportProcessorResult, threshold float64) (bool, error) { a := another.(geomeanProcessorResultPkts) - return gp.geomeanPkts > a.geomeanPkts, nil + percent := (float64(a.geomeanPkts) - float64(gp.geomeanPkts)) / float64(gp.geomeanPkts) * 100.0 + fmt.Printf("Report %s is %.2f%% of report %s\n", a.report.String(), percent, gp.report.String()) + return percent+threshold < 0.0, nil } // compare by average packets received to ensure transitivity -func (gp geomeanProcessorResultMbits) compare(another reportProcessorResult) (bool, error) { +func (gp geomeanProcessorResultMbits) compare(another reportProcessorResult, threshold float64) (bool, error) { a := another.(geomeanProcessorResultMbits) - return gp.geomeanMbits > a.geomeanMbits, nil + percent := (float64(a.geomeanMbits) - float64(gp.geomeanMbits)) / float64(gp.geomeanMbits) * 100.0 + fmt.Printf("Report %s is %.2f%% of report %s\n", a.report.String(), percent, gp.report.String()) + return percent+threshold < 0.0, nil } type geomeanProcessor struct { reportProcessor } -func (gp geomeanProcessor) process(tr *test.TestsuiteReport, verbose bool) reportProcessorResult { +func (gp geomeanProcessor) process(ir *inputReport, verbose bool) reportProcessorResult { if verbose { - fmt.Printf("Parsing report %s\n", tr.Timestamp) + fmt.Printf("Parsing report %s\n", ir.report.Timestamp) } sumlogPkts := 0.0 sumlogMbits := 0.0 sumlogCores := 0.0 - for iii := range tr.Tests { - ttt := tr.Tests[iii] + for iii := range ir.report.Tests { + ttt := ir.report.Tests[iii] + if strings.Index(ttt.TestName, substringFilter) == -1 { + if verbose { + fmt.Printf("Test %s skipped\n", ttt.TestName) + } + continue + } cores := 0 if ttt.CoresStats != nil { @@ -248,9 +277,10 @@ func (gp geomeanProcessor) process(tr *test.TestsuiteReport, verbose bool) repor } return geomeanProcessorResult{ - geomeanPkts: math.Exp2(sumlogPkts / float64(len(tr.Tests))), - geomeanMbits: math.Exp2(sumlogMbits / float64(len(tr.Tests))), - geomeanCores: math.Exp2(sumlogCores / float64(len(tr.Tests))), + report: ir, + geomeanPkts: math.Exp2(sumlogPkts / float64(len(ir.report.Tests))), + geomeanMbits: math.Exp2(sumlogMbits / float64(len(ir.report.Tests))), + geomeanCores: math.Exp2(sumlogCores / float64(len(ir.report.Tests))), } } @@ -262,15 +292,15 @@ type geomeanProcessorMbits struct { geomeanProcessor } -func (gp geomeanProcessorPkts) process(tr *test.TestsuiteReport, verbose bool) reportProcessorResult { +func (gp geomeanProcessorPkts) process(ir *inputReport, verbose bool) reportProcessorResult { return geomeanProcessorResultPkts{ - geomeanProcessorResult: gp.geomeanProcessor.process(tr, verbose).(geomeanProcessorResult), + geomeanProcessorResult: gp.geomeanProcessor.process(ir, verbose).(geomeanProcessorResult), } } -func (gp geomeanProcessorMbits) process(tr *test.TestsuiteReport, verbose bool) reportProcessorResult { +func (gp geomeanProcessorMbits) process(ir *inputReport, verbose bool) reportProcessorResult { return geomeanProcessorResultMbits{ - geomeanProcessorResult: gp.geomeanProcessor.process(tr, verbose).(geomeanProcessorResult), + geomeanProcessorResult: gp.geomeanProcessor.process(ir, verbose).(geomeanProcessorResult), } } @@ -287,8 +317,8 @@ func (tr *testResult) String() string { type sbsProcessorResult struct { reportProcessorResult - suiteName string - results []testResult + report *inputReport + results []testResult } const indentString = " " @@ -298,18 +328,18 @@ const mbitsHeader = " Mbit/s " const coresHeader = " cores" const percents = " pkts/s Mbit/s cores" -func (spr sbsProcessorResult) compare(another reportProcessorResult) (bool, error) { +func (spr sbsProcessorResult) compare(another reportProcessorResult, threshold float64) (bool, error) { a := another.(sbsProcessorResult) if len(spr.results) != len(a.results) { - return false, fmt.Errorf("Reports %s and %s have different number of tests.", spr.suiteName, a.suiteName) + return false, fmt.Errorf("Reports %s and %s have different number of tests.", spr.report.String(), a.report.String()) } col1Len := 0 for iii := range spr.results { if spr.results[iii].name != a.results[iii].name { return false, fmt.Errorf("Reports %s has test named %s while report %s has test named %s. Cannot compare them.", - spr.suiteName, spr.results[iii].name, a.suiteName, a.results[iii].name) + spr.report.String(), spr.results[iii].name, a.report.String(), a.results[iii].name) } if col1Len < len(spr.results[iii].name) { col1Len = len(spr.results[iii].name) @@ -318,23 +348,23 @@ func (spr sbsProcessorResult) compare(another reportProcessorResult) (bool, erro sep2Len := 1 col2Len := len(pktsHeader) + len(mbitsHeader) + len(coresHeader) + sep2Len - if len(spr.suiteName) > col2Len { - sep2Len += len(spr.suiteName) - col2Len - col2Len = len(spr.suiteName) + if len(spr.report.report.Timestamp) > col2Len { + sep2Len += len(spr.report.report.Timestamp) - col2Len + col2Len = len(spr.report.report.Timestamp) } sep3Len := 1 col3Len := len(pktsHeader) + len(mbitsHeader) + len(coresHeader) + sep3Len - if len(a.suiteName) > col2Len { - sep3Len += len(a.suiteName) - col3Len - col3Len = len(a.suiteName) + if len(a.report.report.Timestamp) > col2Len { + sep3Len += len(a.report.report.Timestamp) - col3Len + col3Len = len(a.report.report.Timestamp) } // Print header with report names fmt.Printf("%*s | %*s | %*s\n", col1Len, "", - col2Len, spr.suiteName, - col3Len, a.suiteName) + col2Len, spr.report.report.Timestamp, + col3Len, a.report.report.Timestamp) // Print header with units fmt.Printf("%*s | %s%*s%s%s | %s%*s%s%s | %s\n", col1Len, "", @@ -371,15 +401,16 @@ type sbsProcessorResultMbits struct { } // Return true if at least one test result is better than another result -func (spr sbsProcessorResultPkts) compare(another reportProcessorResult) (bool, error) { +func (spr sbsProcessorResultPkts) compare(another reportProcessorResult, threshold float64) (bool, error) { a := another.(sbsProcessorResultPkts) - _, err := spr.sbsProcessorResult.compare(a.sbsProcessorResult) + _, err := spr.sbsProcessorResult.compare(a.sbsProcessorResult, threshold) if err != nil { return false, err } for iii := range spr.results { - if spr.results[iii].pkts > a.results[iii].pkts { + percent := (float64(a.results[iii].pkts) - float64(spr.results[iii].pkts)) / float64(spr.results[iii].pkts) * 100.0 + if percent+threshold < 0.0 { return true, nil } } @@ -387,15 +418,16 @@ func (spr sbsProcessorResultPkts) compare(another reportProcessorResult) (bool, } // Return true if at least one test result is better than another result -func (spr sbsProcessorResultMbits) compare(another reportProcessorResult) (bool, error) { +func (spr sbsProcessorResultMbits) compare(another reportProcessorResult, threshold float64) (bool, error) { a := another.(sbsProcessorResultMbits) - _, err := spr.sbsProcessorResult.compare(a.sbsProcessorResult) + _, err := spr.sbsProcessorResult.compare(a.sbsProcessorResult, threshold) if err != nil { return false, err } for iii := range spr.results { - if spr.results[iii].mbits > a.results[iii].mbits { + percent := (float64(a.results[iii].mbits) - float64(spr.results[iii].mbits)) / float64(spr.results[iii].mbits) * 100.0 + if percent+threshold < 0.0 { return true, nil } } @@ -406,11 +438,18 @@ type sbsProcessor struct { reportProcessor } -func (sp *sbsProcessor) process(tr *test.TestsuiteReport, verbose bool) reportProcessorResult { - out := make([]testResult, len(tr.Tests)) +func (sp *sbsProcessor) process(ir *inputReport, verbose bool) reportProcessorResult { + out := []testResult{} + + for iii := range ir.report.Tests { + ttt := ir.report.Tests[iii] + if strings.Index(ttt.TestName, substringFilter) == -1 { + if verbose { + fmt.Printf("Test %s skipped\n", ttt.TestName) + } + continue + } - for iii := range tr.Tests { - ttt := tr.Tests[iii] pgbd := ttt.PktgenBenchdata pkts := int64(0) mbits := int64(0) @@ -429,17 +468,17 @@ func (sp *sbsProcessor) process(tr *test.TestsuiteReport, verbose bool) reportPr fmt.Printf("Test %s: pkts: %d, mbits: %d, cores: %d\n", ttt.TestName, pkts, mbits, cores) } } - out[iii] = testResult{ + out = append(out, testResult{ name: ttt.TestName, pkts: pkts, mbits: mbits, cores: cores, - } + }) } return sbsProcessorResult{ - suiteName: tr.Timestamp, - results: out, + report: ir, + results: out, } } @@ -451,14 +490,14 @@ type sbsProcessorMbits struct { sbsProcessor } -func (sp sbsProcessorPkts) process(tr *test.TestsuiteReport, verbose bool) reportProcessorResult { +func (sp sbsProcessorPkts) process(ir *inputReport, verbose bool) reportProcessorResult { return sbsProcessorResultPkts{ - sbsProcessorResult: sp.sbsProcessor.process(tr, verbose).(sbsProcessorResult), + sbsProcessorResult: sp.sbsProcessor.process(ir, verbose).(sbsProcessorResult), } } -func (sp sbsProcessorMbits) process(tr *test.TestsuiteReport, verbose bool) reportProcessorResult { +func (sp sbsProcessorMbits) process(ir *inputReport, verbose bool) reportProcessorResult { return sbsProcessorResultMbits{ - sbsProcessorResult: sp.sbsProcessor.process(tr, verbose).(sbsProcessorResult), + sbsProcessorResult: sp.sbsProcessor.process(ir, verbose).(sbsProcessorResult), } }