├── .gitignore ├── .gitmodules ├── .travis.yml ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── asm ├── asm.go └── asm.s ├── common ├── Makefile ├── common.go ├── common_test.go ├── error.go └── log.go ├── devices ├── bind.go ├── consts.go ├── errno.go ├── misc.go ├── pci.go └── vmbus.go ├── dpdk ├── .gitignore ├── Dockerfile └── Makefile ├── examples ├── .gitignore ├── Dockerfile ├── Makefile ├── OSforwarding.go ├── antiddos │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── antiDDoS.go │ └── generatorForAntiDDoS.go ├── clonablePcapDumper.go ├── copy.go ├── createPacket.go ├── decrementTTL.go ├── demo │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── demo.go │ ├── demoL2_ACL.json │ └── demoL3_ACL.json ├── devbind.go ├── dpi │ ├── Makefile │ ├── README.md │ ├── main │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── dpi.go │ │ ├── handlers.go │ │ └── patterns.json │ └── pattern │ │ ├── Makefile │ │ └── pattern.go ├── dump.go ├── errorHandling.go ├── fileReadWrite │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── fileReadWrite.go │ └── fileReadWriteIn.pcap ├── firewall │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── firewall.conf │ └── firewall.go ├── forwarding │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── forwarding.conf │ └── forwarding.go ├── generate.go ├── gopacketParserExample.go ├── gtpu.go ├── ipsec │ ├── Makefile │ ├── crypt.go │ ├── crypto_mb │ │ ├── aes.go │ │ ├── aes.s │ │ ├── aes_test.go │ │ ├── cbc.go │ │ ├── cbc.s │ │ ├── cbc_test.go │ │ ├── expandKeyAsm.go │ │ ├── expandKeyAsm.s │ │ ├── hmac.go │ │ ├── hmac_test.go │ │ ├── sha1.go │ │ ├── sha1.s │ │ └── sha1_test.go │ ├── ipsec_kernel.go │ ├── perf │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── Makefile │ │ └── ipsec.go │ └── stability │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── ipsec_test.go │ │ ├── stability.go │ │ ├── test.conf │ │ └── test.sh ├── jumbo.go ├── kni.go ├── lb │ ├── Makefile │ ├── balancer.go │ ├── config.go │ ├── main │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── config-aws.json │ │ ├── config.json │ │ └── lb.go │ └── util.go ├── netlink.go ├── nffPktgen │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── generator │ │ ├── generator.go │ │ ├── ipv6.go │ │ ├── parseConfig.go │ │ └── utility.go │ ├── gtp-u │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── gen-ip4gtp-u.json │ │ ├── ip4gtp-u-sarp.json │ │ ├── ip4gtp-u.json │ │ ├── rec-ip4gtp-u.json │ │ └── trafficgen.go │ └── testing │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── README.md │ │ ├── arp.json │ │ ├── arpVlan.json │ │ ├── config.json │ │ ├── dump.go │ │ ├── ether.json │ │ ├── ip4.json │ │ ├── ip4icmp.json │ │ ├── ip4tcp.json │ │ ├── ip4tcpVlan.json │ │ ├── ip4udp.json │ │ ├── ip4udpVlan.json │ │ ├── ip6.json │ │ ├── ip6icmp.json │ │ ├── ip6tcp.json │ │ ├── ip6udp.json │ │ ├── minPktLoss.go │ │ ├── mix.json │ │ ├── pcap.json │ │ ├── perfTest.go │ │ ├── run.sh │ │ ├── sendGetBack.go │ │ ├── test.pcap │ │ ├── testnat.json │ │ └── vlanTag.json ├── pingReplay.go ├── sendFixedPktsNumber.go ├── timer.go └── tutorial │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── NFF-Go tutorial.pdf │ ├── common.go │ ├── config.json │ ├── genscripts.go │ ├── rules1.conf │ ├── rules2.conf │ ├── runpktgen.sh │ ├── step01.go │ ├── step02.go │ ├── step03.go │ ├── step04.go │ ├── step05.go │ ├── step06.go │ ├── step07.go │ ├── step08.go │ ├── step09.go │ ├── step10.go │ └── step11.go ├── flow ├── counters.go ├── flow.go ├── predefined.go └── scheduler.go ├── go.mod ├── go.sum ├── internal └── low │ ├── Makefile │ ├── low.go │ ├── low.h │ ├── low_bpf.go │ ├── low_mlx.go │ ├── low_no_mlx.go │ └── low_test.go ├── mk ├── include.mk ├── intermediate.mk └── leaf.mk ├── nff-go-base ├── .gitignore └── Makefile ├── packet ├── Makefile ├── acl.go ├── acl_internal_test.go ├── arp.go ├── arp_test.go ├── checksum.go ├── checksum_test.go ├── gre.go ├── gtp.go ├── icmp6.go ├── lpm_test.go ├── mpls.go ├── mpls_test.go ├── neigh.go ├── packet.go ├── packet_test.go ├── pcap_utils.go ├── pcap_utils_internal_test.go ├── utils_for_test.go ├── vlan.go └── vlan_test.go ├── scripts └── get-depends.sh ├── test ├── Makefile ├── framework │ ├── .gitignore │ ├── Makefile │ ├── apptype_string.go │ ├── config.go │ ├── dockerlauncher.go │ ├── logging.go │ ├── main │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── config.json │ │ ├── latency.json │ │ ├── perf.json │ │ ├── perf_compare.go │ │ ├── report_compare.go │ │ ├── stability.json │ │ └── tf.go │ ├── report.go │ ├── report_test.go │ ├── testsuite.go │ └── types.go ├── performance │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── ipsec.go │ ├── latency.go │ ├── perf_count.go │ ├── perf_gen.go │ ├── perf_light.go │ ├── perf_main.go │ └── perf_seq.go ├── stability │ ├── Makefile │ ├── stabilityCommon │ │ └── common.go │ ├── testCksum │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── checksum_test.go │ │ ├── testCksum.go │ │ └── testCksumCommon │ │ │ └── testCksumCommon.go │ ├── testMerge │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── merge_test.go │ │ └── testMerge.go │ └── testSingleWorkingFF │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── singleWorkingFF_test.go │ │ ├── test-handle-l3rules.conf │ │ ├── test-separate-l3rules.conf │ │ ├── test-split.conf │ │ └── testSingleWorkingFF.go └── stash │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── forwardingTestL3.go │ ├── forwardingTestL3_ACL.conf │ ├── forwardingTestL3_ACL.json │ ├── linuxReorderTestReceive.go │ ├── linuxReorderTestSend.go │ ├── sendback.go │ └── sendback.json ├── types ├── Makefile ├── const.go ├── ipv4.go ├── ipv6.go ├── mac.go └── subnet.go └── vagrant ├── .gitignore ├── README.md ├── Vagrantfile ├── getports.sh └── scripts.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # emacs 2 | *~ 3 | doc 4 | GPATH 5 | GTAGS 6 | GRTAGS 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dpdk/dpdk"] 2 | path = dpdk/dpdk 3 | url = http://dpdk.org/git/dpdk 4 | [submodule "dpdk/pktgen-dpdk"] 5 | path = dpdk/pktgen-dpdk 6 | url = http://dpdk.org/git/apps/pktgen-dpdk 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | 4 | dist: 5 | - bionic 6 | 7 | sudo: 8 | - required 9 | 10 | services: 11 | - docker 12 | 13 | before_script: 14 | - sudo apt-get install -y linux-headers-$(uname -r) 15 | - docker pull ubuntu:focal 16 | - docker build --build-arg https_proxy=${https_proxy} -t test-focal . 17 | - docker run -it -d --privileged -v /usr/src:/usr/src -v /lib/modules:/lib/modules -v /sys/devices/system/node:/sys/devices/system/node --name test-nff-go test-focal /bin/bash 18 | 19 | script: 20 | - docker exec -i test-nff-go go mod download 21 | - docker exec -i test-nff-go make 22 | # Build standalone examples 23 | - docker exec -i test-nff-go bash -c "cd examples && make gopacketParserExample && cd .." 24 | - docker exec -i test-nff-go bash -c "cd examples && make nffPktgen && cd -" 25 | - docker exec -i test-nff-go make -C examples/dpi 26 | # Run unit tests 27 | - docker exec -i test-nff-go sysctl -w vm.nr_hugepages=1024 28 | - docker exec -i test-nff-go sh -c 'echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages' 29 | - docker exec -i test-nff-go mkdir /mnt/huge 30 | - docker exec -i test-nff-go mount -t hugetlbfs nodev /mnt/huge 31 | - docker exec -i test-nff-go make citesting 32 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to NFF-GO 2 | 3 | NFF-GO is an open source project licensed under the BSD-style license which can be found in the LICENSE file. 4 | 5 | ## Coding Style 6 | 7 | NFF-GO follows the standard formatting recommendations and language idioms set out 8 | in the [Effective Go](https://golang.org/doc/effective_go.html) guide. It's 9 | definitely worth reading - but the relevant sections are 10 | [formatting](https://golang.org/doc/effective_go.html#formatting) 11 | and [names](https://golang.org/doc/effective_go.html#names). 12 | 13 | ## Certificate of Origin 14 | 15 | In order to get a clear contribution chain of trust we use the [signed-off-by language](https://01.org/community/signed-process) 16 | used by the Linux kernel project. 17 | 18 | ## Patch format 19 | 20 | Beside the signed-off-by footer, we expect each patch to comply with the following format: 21 | 22 | ``` 23 | : Change summary 24 | 25 | More detailed explanation of your changes: Why and how. 26 | Wrap it to 72 characters. 27 | See [here](http://chris.beams.io/posts/git-commit/) 28 | for some more good advices. 29 | 30 | Signed-off-by: 31 | ``` 32 | 33 | ## Pull requests 34 | 35 | We accept github pull requests. 36 | 37 | If you want to work on github.com/intel-go/nff-go and your fork on the same workstation you will need to use multiple GOPATHs. Assuming this is the case 38 | 39 | 1. Open a terminal 40 | 2. mkdir -p ~/go-fork/src/github.com/intel-go (replacing go-fork with your preferred location) 41 | 3. export GOPATH=~/go-fork 42 | 4. cd $GOPATH/src/github.com/intel-go/nff-go 43 | 5. git clone https://github.com/GITHUB-USERNAME/nff-go.git (replace GITHUB-USERNAME with your username) 44 | 6. cd nff-go 45 | 7. go install ./... 46 | 47 | Once you've finished making your changes push them to your fork and send the PR via the github UI. If you don't need to maintain the github.com/intel-go/nff-go repo and your fork on the same workstation you can skip steps 2 and 3. 48 | 49 | ## Quality Controls 50 | 51 | We request you give quality assurance some consideration by: 52 | * Adding go unit tests for changes where it makes sense. 53 | 54 | ## Issue tracking 55 | 56 | If you have a problem, please let us know. Write e-mail to [maintainers](mailto:areg.melik-adamyan@intel.com) 57 | 58 | If a bug is not already documented, by all means please [open an 59 | issue in github](https://github.com/intel-go/NFF-GO/issues/new) so we all get visibility 60 | the problem and work toward resolution. 61 | 62 | For feature requests we're also using github issues, with the label 63 | "enhancement". 64 | 65 | ## Closing issues 66 | 67 | You can either close issues manually by adding the fixing commit SHA1 to the issue 68 | comments or by adding the `Fixes` keyword to your commit message: 69 | 70 | ``` 71 | flow: test: Add Stop checking tests 72 | 73 | We check that we get the right response when stopping flow. 74 | 75 | Fixes #121 76 | 77 | Signed-off-by: Ilia Filippov 78 | ``` 79 | 80 | Github will then automatically close that issue when parsing the 81 | [commit message](https://help.github.com/articles/closing-issues-via-commit-messages/). 82 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:focal 2 | 3 | ARG MAKEFLAGS=-j2 4 | ARG DEBIAN_FRONTEND=noninteractive 5 | 6 | ENV GOROOT /opt/go 7 | ENV PATH ${GOROOT}/bin:${GOPATH}/bin:${PATH} 8 | ENV NFF_GO /nff-go 9 | 10 | RUN apt-get -q update && apt-get -q -y install \ 11 | make \ 12 | build-essential \ 13 | git \ 14 | curl \ 15 | wget \ 16 | libpcap-dev \ 17 | libelf-dev \ 18 | libhugetlbfs-bin \ 19 | libnuma-dev \ 20 | libhyperscan-dev \ 21 | liblua5.3-dev \ 22 | libmnl-dev \ 23 | libibverbs-dev 24 | 25 | RUN cd /opt && curl -L -s https://dl.google.com/go/go1.13.1.linux-amd64.tar.gz | tar zx 26 | RUN git clone -b v0.0.4 https://github.com/libbpf/libbpf 27 | RUN make -C libbpf/src all install 28 | RUN echo "/usr/lib64" > /etc/ld.so.conf.d/usrlib64.conf 29 | RUN ldconfig 30 | 31 | RUN mkdir -p ${NFF_GO} 32 | COPY . ${NFF_GO} 33 | 34 | WORKDIR ${NFF_GO} 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, Intel Corporation 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of Intel Corporation nor the names of its contributors 12 | may be used to endorse or promote products derived from this software 13 | without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = mk 6 | SUBDIRS = nff-go-base dpdk test examples 7 | CI_TESTING_TARGETS = packet internal/low common 8 | TESTING_TARGETS = $(CI_TESTING_TARGETS) test/stability 9 | 10 | all: $(SUBDIRS) 11 | 12 | debug: 13 | $(MAKE) all NFF_GO_DEBUG=y 14 | 15 | dpdk: nff-go-base 16 | 17 | test: dpdk 18 | 19 | examples: dpdk 20 | 21 | perf_testing: 22 | $(MAKE) -C test perf_testing 23 | 24 | .PHONY: testing $(TESTING_TARGETS) 25 | .NOTPARALLEL: testing $(TESTING_TARGETS) 26 | testing: $(TESTING_TARGETS) 27 | 28 | .PHONY: citesting $(CI_TESTING_TARGETS) 29 | .NOTPARALLEL: citesting $(CI_TESTING_TARGETS) 30 | citesting: $(CI_TESTING_TARGETS) 31 | 32 | $(TESTING_TARGETS): 33 | $(MAKE) -C $@ testing 34 | 35 | include $(PATH_TO_MK)/intermediate.mk 36 | -------------------------------------------------------------------------------- /asm/asm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package asm 6 | 7 | // RteCompilerRmb is lfence 8 | func RteCompilerRmb() 9 | 10 | // RteCompilerWmb is sfence 11 | func RteCompilerWmb() 12 | 13 | // Prefetcht0 is prefetch 14 | func Prefetcht0(addr uintptr) 15 | 16 | func GenerateMask(v1 *([32]uint8), v2 *([32]uint8), previousMask *([32]bool), result *([32]bool)) bool 17 | -------------------------------------------------------------------------------- /asm/asm.s: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | #include "textflag.h" 6 | TEXT ·RteCompilerRmb(SB),NOSPLIT,$0-0 7 | LFENCE 8 | RET 9 | TEXT ·RteCompilerWmb(SB),NOSPLIT,$0-0 10 | SFENCE 11 | RET 12 | TEXT ·Prefetcht0(SB),NOSPLIT,$0-8 13 | MOVQ addr+0(FP), AX 14 | PREFETCHT0 (AX) 15 | RET 16 | TEXT ·GenerateMask(SB),NOSPLIT,$0-33 17 | MOVQ v1+0(FP), AX 18 | MOVQ v2+8(FP), BX 19 | MOVQ previousMask+16(FP), CX 20 | MOVQ result+24(FP), DX 21 | VMOVDQU (AX), Y0 22 | VMOVDQU (BX), Y1 23 | VMOVDQU (CX), Y2 24 | VPCMPEQB Y0, Y1, Y0 25 | VPAND Y0, Y2, Y0 26 | VPTEST Y0, Y0 27 | SETEQ a+32(FP) 28 | VMOVDQU Y0, (DX) 29 | VZEROUPPER 30 | RET 31 | -------------------------------------------------------------------------------- /common/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../mk 6 | include $(PATH_TO_MK)/include.mk 7 | 8 | .PHONY: testing 9 | testing: check-pktgen 10 | go test -tags "${GO_BUILD_TAGS}" 11 | 12 | .PHONY: coverage 13 | coverage: 14 | go test -cover -coverprofile=c.out 15 | go tool cover -html=c.out -o common_coverage.html 16 | -------------------------------------------------------------------------------- /common/common.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package common is used for combining common functions from other packages 6 | // which aren't connected with C language part 7 | package common 8 | 9 | import ( 10 | "strconv" 11 | ) 12 | 13 | // GetDefaultCPUs returns default core list {0, 1, ..., NumCPU} 14 | func GetDefaultCPUs(cpuNumber int) []int { 15 | cpus := make([]int, cpuNumber, cpuNumber) 16 | for i := 0; i < cpuNumber; i++ { 17 | cpus[i] = i 18 | } 19 | return cpus 20 | } 21 | 22 | // HandleCPUs parses cpu list string into array of valid core numbers. 23 | // Removes duplicates 24 | func HandleCPUList(s string, maxcpu int) ([]int, error) { 25 | nums, err := parseCPUs(s) 26 | nums = removeDuplicates(nums) 27 | nums = dropInvalidCPUs(nums, maxcpu) 28 | return nums, err 29 | } 30 | 31 | // parseCPUs parses cpu list string into array of cpu numbers 32 | func parseCPUs(s string) ([]int, error) { 33 | var startRange, k int 34 | nums := make([]int, 0, 256) 35 | if s == "" { 36 | return nums, nil 37 | } 38 | startRange = -1 39 | var err error 40 | for i, j := 0, 0; i <= len(s); i++ { 41 | if i != len(s) && s[i] == '-' { 42 | startRange, err = strconv.Atoi(s[j:i]) 43 | if err != nil { 44 | return nums, WrapWithNFError(err, "parsing of CPU list failed", ParseCPUListErr) 45 | } 46 | j = i + 1 47 | } 48 | 49 | if i == len(s) || s[i] == ',' { 50 | r, err := strconv.Atoi(s[j:i]) 51 | if err != nil { 52 | return nums, WrapWithNFError(err, "parsing of CPU list failed", ParseCPUListErr) 53 | } 54 | if startRange != -1 { 55 | if startRange > r { 56 | return nums, WrapWithNFError(nil, "CPU range is invalid, min should not exceed max", InvalidCPURangeErr) 57 | } 58 | for k = startRange; k <= r; k++ { 59 | nums = append(nums, k) 60 | } 61 | startRange = -1 62 | } else { 63 | nums = append(nums, r) 64 | } 65 | if i == len(s) { 66 | break 67 | } 68 | j = i + 1 69 | } 70 | } 71 | return nums, nil 72 | } 73 | 74 | func removeDuplicates(array []int) []int { 75 | result := []int{} 76 | seen := map[int]bool{} 77 | for _, val := range array { 78 | if _, ok := seen[val]; !ok { 79 | result = append(result, val) 80 | seen[val] = true 81 | } 82 | } 83 | return result 84 | } 85 | 86 | // dropInvalidCPUs validates cpu list. Takes array of cpu ids and checks it is < maxcpu on machine, 87 | // invalid are excluded. Returns list of valid cpu ids. 88 | func dropInvalidCPUs(nums []int, maxcpu int) []int { 89 | i := 0 90 | for _, x := range nums { 91 | if x < maxcpu { 92 | nums[i] = x 93 | i++ 94 | } else { 95 | LogWarning(Initialization, "Requested cpu", x, "exceeds maximum cores number on machine, skip it") 96 | } 97 | } 98 | return nums[:i] 99 | } 100 | 101 | // RXTXStats describes statistics for sender or receiver flow function 102 | // node. 103 | type RXTXStats struct { 104 | PacketsProcessed, PacketsDropped, BytesProcessed uint64 105 | } 106 | -------------------------------------------------------------------------------- /common/log.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package common 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | "os" 11 | ) 12 | 13 | // LogType - type of logging, used in flow package 14 | type LogType uint8 15 | 16 | const ( 17 | // No - no output even after fatal errors 18 | No LogType = 1 << iota 19 | // Initialization - output during system initialization 20 | Initialization = 2 21 | // Debug - output during execution one time per time period (scheduler ticks) 22 | Debug = 4 23 | // Verbose - output during execution as soon as something happens. Can influence performance 24 | Verbose = 8 25 | ) 26 | 27 | var currentLogType = No | Initialization | Debug 28 | 29 | // LogFatal internal, used in all packages 30 | func LogFatal(logType LogType, v ...interface{}) { 31 | if logType¤tLogType != 0 { 32 | t := fmt.Sprintln(v...) 33 | log.Fatal("ERROR: ", t) 34 | } 35 | os.Exit(1) 36 | } 37 | 38 | // LogFatalf is a wrapper at LogFatal which makes formatting before logger. 39 | func LogFatalf(logType LogType, format string, v ...interface{}) { 40 | LogFatal(logType, fmt.Sprintf(format, v...)) 41 | } 42 | 43 | // LogError internal, used in all packages 44 | func LogError(logType LogType, v ...interface{}) string { 45 | if logType¤tLogType != 0 { 46 | t := fmt.Sprintln(v...) 47 | log.Print("ERROR: ", t) 48 | return t 49 | } 50 | return "" 51 | } 52 | 53 | // LogWarning internal, used in all packages 54 | func LogWarning(logType LogType, v ...interface{}) { 55 | if logType¤tLogType != 0 { 56 | t := fmt.Sprintln(v...) 57 | log.Print("WARNING: ", t) 58 | } 59 | } 60 | 61 | // LogDebug internal, used in all packages 62 | func LogDebug(logType LogType, v ...interface{}) { 63 | if logType¤tLogType != 0 { 64 | t := fmt.Sprintln(v...) 65 | log.Print("DEBUG: ", t) 66 | } 67 | } 68 | 69 | // LogDrop internal, used in all packages 70 | func LogDrop(logType LogType, v ...interface{}) { 71 | if logType¤tLogType != 0 { 72 | t := fmt.Sprintln(v...) 73 | log.Print("DROP: ", t) 74 | } 75 | } 76 | 77 | // LogTitle internal, used in all packages 78 | func LogTitle(logType LogType, v ...interface{}) { 79 | if logType¤tLogType != 0 { 80 | log.Print(v...) 81 | } 82 | } 83 | 84 | // SetLogType internal, used in flow package 85 | func SetLogType(logType LogType) { 86 | log.SetFlags(0) 87 | currentLogType = logType 88 | } 89 | 90 | // GetDPDKLogLevel internal, used in flow package 91 | func GetDPDKLogLevel() string { 92 | switch currentLogType { 93 | case No: 94 | return "0" 95 | case No | Initialization: 96 | return "7" 97 | case No | Initialization | Debug: 98 | return "8" 99 | case No | Initialization | Debug | Verbose: 100 | return "8" 101 | default: 102 | return "8" 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /devices/bind.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package devices helps to query DPDK compatibles devices and to bind/unbind drivers 6 | package devices 7 | 8 | // Device is a DPDK compatible device and should be able to bind, unbind and 9 | // probe. 10 | type Device interface { 11 | // Binds a driver to the device 12 | Bind(driver string) error 13 | // Unbinds the current driver from the device 14 | Unbind() error 15 | // Returns the name of the driver that is currently bound 16 | CurrentDriver() (string, error) 17 | // Probes the currently bound driver and checks if there is an error 18 | Probe() error 19 | // Returns the ID of the device 20 | ID() string 21 | } 22 | 23 | // New returns a corresponding device by given input 24 | func New(input string) (Device, error) { 25 | switch { 26 | case IsPciID.Match([]byte(input)): 27 | return NewDeviceByPciID(input) 28 | case IsUUID.Match([]byte(input)): 29 | return NewDeviceByVmbusID(input) 30 | default: 31 | return NewDeviceByNicName(input) 32 | } 33 | } 34 | 35 | // NewDeviceByPciID returns a PCI device by given PCI ID 36 | func NewDeviceByPciID(pciID string) (Device, error) { 37 | device, err := GetPciDeviceByPciID(pciID) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | return device, nil 43 | } 44 | 45 | // NewDeviceByVmbusID returns a VMBus device by given UUID 46 | func NewDeviceByVmbusID(uuid string) (Device, error) { 47 | device, err := GetVmbusDeviceByUUID(uuid) 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | return device, nil 53 | } 54 | 55 | // NewDeviceByNicName returns a device by given NIC name, e.g. eth0. 56 | func NewDeviceByNicName(nicName string) (Device, error) { 57 | devID, err := GetDeviceID(nicName) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | device, err := newDevice(devID) 63 | if err != nil { 64 | return nil, err 65 | } 66 | 67 | return device, nil 68 | } 69 | 70 | func newDevice(id string) (Device, error) { 71 | if IsPciID.Match([]byte(id)) { 72 | return GetPciDeviceByPciID(id) 73 | } 74 | return GetVmbusDeviceByUUID(id) 75 | } 76 | -------------------------------------------------------------------------------- /devices/errno.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package devices helps to query DPDK compatibles devices and to bind/unbind drivers 6 | package devices 7 | 8 | import ( 9 | "errors" 10 | ) 11 | 12 | // Errors of devices package 13 | var ( 14 | ErrNoBoundDriver = errors.New("no driver is bound to the device") 15 | ErrAlreadyBoundDriver = errors.New("device has already bound the selected driver") 16 | ErrBind = errors.New("fail to bind the driver") 17 | ErrUnbind = errors.New("fail to unbind the driver") 18 | ErrUnsupportedDriver = errors.New("unsupported DPDK driver") 19 | ErrNotProbe = errors.New("device doesn't support 'drive_probe'") 20 | ErrKernelModuleNotLoaded = errors.New("kernel module is not loaded") 21 | ) 22 | -------------------------------------------------------------------------------- /dpdk/.gitignore: -------------------------------------------------------------------------------- 1 | pktgen 2 | Pktgen.lua 3 | dpdk-* 4 | *.pg 5 | -------------------------------------------------------------------------------- /dpdk/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | EXPOSE 22022 11 | 12 | #Uncomment for Fedora 13 | # RUN dnf -y install pciutils; dnf clean all 14 | 15 | WORKDIR /workdir 16 | COPY pktgen . 17 | 18 | # Workaround for linking agains libpcap.so.0.8 on Ubuntu 19 | # Uncomment for Fedora 20 | #RUN ln -s libpcap.so.1 /usr/lib64/libpcap.so.0.8 21 | 22 | CMD ["./pktgen", "-c", "0x1ff", "-n", "4", "--", "-P", "-m", "[1:1-2].0, [3:3-4].1, [5-6:5].2, [7-8:7].3", "-G"] 23 | -------------------------------------------------------------------------------- /dpdk/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../mk 6 | IMAGENAME = nff-go-pktgen 7 | 8 | # Pktgen variables 9 | NOCHECK_PKTGEN = yes 10 | 11 | include $(PATH_TO_MK)/leaf.mk 12 | 13 | # Disable FSGSBASE and F16C to run in VMs and Docker containers. 14 | export EXTRA_CFLAGS = -mno-fsgsbase -mno-f16c 15 | ifdef NFF_GO_DEBUG 16 | export EXTRA_CFLAGS += -g -O0 17 | endif 18 | 19 | .PHONY: dpdk 20 | dpdk: all 21 | 22 | all: pktgen 23 | 24 | $(DPDK_DIR)/$(DPDK_INSTALL_DIR): 25 | $(MAKE) -C $(DPDK_DIR) config T=$(RTE_TARGET) 26 | @if [ -z '${NFF_GO_NO_MLX_DRIVERS}' ]; then \ 27 | echo BUILDING DPDK WITH MLX DRIVERS; \ 28 | sed -ri 's,(MLX._PMD=)n,\1y,' $(DPDK_DIR)/build/.config; \ 29 | else \ 30 | echo BUILDING DPDK WITHOUT MLX DRIVERS; \ 31 | fi 32 | $(MAKE) -C $(DPDK_DIR) 33 | $(MAKE) -C $(DPDK_DIR) install DESTDIR=$(DPDK_INSTALL_DIR) 34 | 35 | $(PKTGEN_DIR)/app/$(RTE_TARGET)/pktgen: $(DPDK_DIR)/$(DPDK_INSTALL_DIR) 36 | $(MAKE) -C $(PKTGEN_DIR) 37 | 38 | pktgen: $(PKTGEN_DIR)/app/$(RTE_TARGET)/pktgen 39 | cp $(PKTGEN_DIR)/app/$(RTE_TARGET)/pktgen . 40 | 41 | clean: 42 | -$(MAKE) -C $(PKTGEN_DIR) realclean 43 | -rm pktgen 44 | -$(MAKE) -C $(DPDK_DIR) clean 45 | -rm -rf $(DPDK_DIR)/$(DPDK_INSTALL_DIR) $(DPDK_DIR)/build 46 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | dump 2 | clonablePcapDumper 3 | kni 4 | copy 5 | gopacketParserExample 6 | errorHandling 7 | createPacket 8 | sendFixedPktsNumber 9 | gtpu 10 | pingReplay 11 | timer 12 | netlink 13 | devbind 14 | OSforwarding 15 | generate 16 | jumbo 17 | decrementTTL 18 | -------------------------------------------------------------------------------- /examples/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY dump . 12 | COPY clonablePcapDumper . 13 | COPY kni . 14 | COPY copy . 15 | COPY createPacket . 16 | COPY sendFixedPktsNumber . 17 | COPY errorHandling . 18 | COPY gtpu . 19 | COPY pingReplay . 20 | COPY timer . 21 | COPY netlink . 22 | COPY generate . 23 | COPY OSforwarding . 24 | COPY jumbo . 25 | COPY decrementTTL . 26 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../mk 6 | IMAGENAME = nff-go-examples 7 | EXECUTABLES = dump clonablePcapDumper kni copy errorHandling timer \ 8 | createPacket sendFixedPktsNumber gtpu pingReplay \ 9 | netlink gopacketParserExample devbind generate \ 10 | OSforwarding jumbo decrementTTL 11 | SUBDIRS = tutorial antiddos demo fileReadWrite firewall forwarding ipsec lb nffPktgen 12 | 13 | .PHONY: dpi 14 | dpi: 15 | $(MAKE) -C dpi 16 | 17 | include $(PATH_TO_MK)/intermediate.mk 18 | include $(PATH_TO_MK)/leaf.mk 19 | -------------------------------------------------------------------------------- /examples/OSforwarding.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "github.com/intel-go/nff-go/flow" 10 | ) 11 | 12 | func main() { 13 | // If you use af-xdp mode you need to configure queues: 14 | // e.g. ethtool -N my_device flow-type tcp4 dst-port 4242 action 16 15 | afXDP := flag.Bool("af-xdp", false, "use af-xdp. need to use ethtool to setup queues") 16 | inport := flag.String("in", "", "device for receiver") 17 | inQueue := flag.Int("in-queue", 16, "queue for receiver") 18 | outport := flag.String("out", "", "device for sender") 19 | flag.Parse() 20 | 21 | flow.CheckFatal(flow.SystemInit(nil)) 22 | if *afXDP { 23 | inputFlow, err := flow.SetReceiverXDP(*inport, *inQueue) 24 | flow.CheckFatal(err) 25 | flow.CheckFatal(flow.SetSenderXDP(inputFlow, *outport)) 26 | } else { 27 | inputFlow, err := flow.SetReceiverOS(*inport) 28 | flow.CheckFatal(err) 29 | flow.CheckFatal(flow.SetSenderOS(inputFlow, *outport)) 30 | } 31 | flow.CheckFatal(flow.SystemStart()) 32 | } 33 | -------------------------------------------------------------------------------- /examples/antiddos/.gitignore: -------------------------------------------------------------------------------- 1 | antiDDoS 2 | generatorForAntiDDoS 3 | -------------------------------------------------------------------------------- /examples/antiddos/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | 12 | COPY antiDDoS . 13 | COPY generatorForAntiDDoS . 14 | -------------------------------------------------------------------------------- /examples/antiddos/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | IMAGENAME = anti-ddos 7 | EXECUTABLES = generatorForAntiDDoS antiDDoS 8 | 9 | include $(PATH_TO_MK)/leaf.mk 10 | -------------------------------------------------------------------------------- /examples/clonablePcapDumper.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "log" 11 | "os" 12 | 13 | "github.com/intel-go/nff-go/flow" 14 | "github.com/intel-go/nff-go/packet" 15 | ) 16 | 17 | var ( 18 | cloneNumber uint 19 | ) 20 | 21 | func main() { 22 | inport := flag.Uint("outport", 1, "port for sender") 23 | outport := flag.Uint("inport", 0, "port for receiver") 24 | flag.Parse() 25 | 26 | // Initialize NFF-GO library at 10 available cores 27 | config := flow.Config{ 28 | CPUList: "0-9", 29 | } 30 | flow.CheckFatal(flow.SystemInit(&config)) 31 | 32 | // Receive packets from zero port. One queue will be added automatically. 33 | f1, err := flow.SetReceiver(uint16(*inport)) 34 | flow.CheckFatal(err) 35 | 36 | var pdp pcapdumperParameters 37 | flow.CheckFatal(flow.SetHandler(f1, pcapdumper, &pdp)) 38 | 39 | // Send packets to control speed. One queue will be added automatically. 40 | flow.CheckFatal(flow.SetSender(f1, uint16(*outport))) 41 | 42 | flow.CheckFatal(flow.SystemStart()) 43 | } 44 | 45 | type pcapdumperParameters struct { 46 | f *os.File 47 | } 48 | 49 | func (pd pcapdumperParameters) Copy() interface{} { 50 | filename := fmt.Sprintf("dumped%d.pcap", cloneNumber) 51 | f, err := os.Create(filename) 52 | if err != nil { 53 | fmt.Println("Cannot create file: ", err) 54 | os.Exit(0) 55 | } 56 | cloneNumber++ 57 | if err := packet.WritePcapGlobalHdr(f); err != nil { 58 | log.Fatal(err) 59 | } 60 | pdp := pcapdumperParameters{f: f} 61 | return pdp 62 | } 63 | 64 | func (pd pcapdumperParameters) Delete() { 65 | pd.f.Close() 66 | } 67 | 68 | func pcapdumper(currentPacket *packet.Packet, context flow.UserContext) { 69 | pd := context.(pcapdumperParameters) 70 | if err := currentPacket.WritePcapOnePacket(pd.f); err != nil { 71 | log.Fatal(err) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /examples/copy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "github.com/intel-go/nff-go/flow" 9 | ) 10 | 11 | func main() { 12 | flow.CheckFatal(flow.SystemInit(nil)) 13 | 14 | a, err := flow.SetReceiver(0) 15 | flow.CheckFatal(err) 16 | 17 | b, err := flow.SetCopier(a) 18 | flow.CheckFatal(err) 19 | 20 | flow.CheckFatal(flow.SetSender(a, 1)) 21 | flow.CheckFatal(flow.SetSender(b, 2)) 22 | 23 | flow.CheckFatal(flow.SystemStart()) 24 | } 25 | -------------------------------------------------------------------------------- /examples/createPacket.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "encoding/hex" 9 | "flag" 10 | 11 | "github.com/intel-go/nff-go/flow" 12 | "github.com/intel-go/nff-go/packet" 13 | ) 14 | 15 | var firstFlow *flow.Flow 16 | var buffer []byte 17 | 18 | func main() { 19 | var err error 20 | // By default this example generates 128-byte empty packets with 21 | // InitEmptyIPv4TCPPacket() and set Ethernet destination address. 22 | // If flag enabled, generates packets with GeneratePacketFromByte() from raw buffer. 23 | enablePacketFromByte := flag.Bool("pfb", false, "enables generating packets with GeneratePacketFromByte() from raw buffer. Otherwise, by default empty 128-byte packets are generated") 24 | flag.Parse() 25 | 26 | // Initialize NFF-GO library at 16 available cores 27 | config := flow.Config{ 28 | CPUList: "0-15", 29 | } 30 | flow.CheckFatal(flow.SystemInit(&config)) 31 | // Create packets with speed at least 1000 packets/s 32 | if *enablePacketFromByte == false { 33 | firstFlow, _, err = flow.SetFastGenerator(generatePacket, 1000, nil) 34 | flow.CheckFatal(err) 35 | } else { 36 | buffer, _ = hex.DecodeString("00112233445501112131415108004500002ebffd00000406747a7f0000018009090504d2162e123456781234569050102000ffe60000") 37 | firstFlow, _, err = flow.SetFastGenerator(generatePacketFromByte, 1000, nil) 38 | flow.CheckFatal(err) 39 | } 40 | // Send all generated packets to the output 41 | flow.CheckFatal(flow.SetSender(firstFlow, 1)) 42 | flow.CheckFatal(flow.SystemStart()) 43 | } 44 | 45 | func generatePacket(pkt *packet.Packet, context flow.UserContext) { 46 | // Total packet size will be 14+20+20+70+4(crc)=128 bytes 47 | if packet.InitEmptyPacket(pkt, 70) == true { 48 | pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55} 49 | } 50 | } 51 | 52 | func generatePacketFromByte(emptyPacket *packet.Packet, context flow.UserContext) { 53 | // Total packet size is 64 bytes 54 | packet.GeneratePacketFromByte(emptyPacket, buffer) 55 | } 56 | -------------------------------------------------------------------------------- /examples/decrementTTL.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | ) 13 | 14 | // Main function for constructing packet processing graph. 15 | func main() { 16 | inPort := flag.Uint("inPort", 0, "port for receiver") 17 | outPort := flag.Uint("outPort", 1, "port for sender") 18 | flag.Parse() 19 | 20 | flow.SystemInit(nil) 21 | inputFlow, _ := flow.SetReceiver(uint16(*inPort)) 22 | flow.SetHandlerDrop(inputFlow, decrementTTL, nil) 23 | flow.SetSender(inputFlow, uint16(*outPort)) 24 | flow.SystemStart() 25 | } 26 | 27 | func decrementTTL(current *packet.Packet, c flow.UserContext) bool { 28 | current.ParseL3() // must parse before header can be read 29 | header := current.GetIPv4() 30 | if header == nil { // not IPv4 31 | return false 32 | } 33 | 34 | header.TimeToLive-- 35 | if header.TimeToLive == 0 { // TTL exceeded, drop 36 | return false 37 | } else { 38 | return true 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/demo/.gitignore: -------------------------------------------------------------------------------- 1 | demo -------------------------------------------------------------------------------- /examples/demo/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | 12 | COPY demo . 13 | COPY demoL2_ACL.json . 14 | COPY demoL3_ACL.json . 15 | -------------------------------------------------------------------------------- /examples/demo/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | IMAGENAME = nff-go-example-demo 7 | EXECUTABLES = demo 8 | 9 | include $(PATH_TO_MK)/leaf.mk 10 | -------------------------------------------------------------------------------- /examples/demo/demo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "time" 10 | 11 | "github.com/intel-go/nff-go/flow" 12 | "github.com/intel-go/nff-go/packet" 13 | ) 14 | 15 | var ( 16 | l2Rules *packet.L2Rules 17 | l3Rules *packet.L3Rules 18 | load uint 19 | ) 20 | 21 | func main() { 22 | var err error 23 | flag.UintVar(&load, "load", 1000, "Use this for regulating 'load intensity', number of iterations") 24 | inport := flag.Uint("inport", 0, "port for receiver") 25 | outport1 := flag.Uint("outport1", 1, "port for 1st sender") 26 | outport2 := flag.Uint("outport2", 2, "port for 2nd sender") 27 | flag.Parse() 28 | 29 | // Initialize NFF-GO library at 16 cores by default 30 | config := flow.Config{ 31 | CPUList: "0-15", 32 | NoPacketHeadChange: true, 33 | } 34 | flow.CheckFatal(flow.SystemInit(&config)) 35 | 36 | // Start regular updating forwarding rules 37 | l2Rules, err = packet.GetL2ACLFromJSON("demoL2_ACL.json") 38 | flow.CheckFatal(err) 39 | l3Rules, err = packet.GetL3ACLFromJSON("demoL3_ACL.json") 40 | flow.CheckFatal(err) 41 | go updateSeparateRules() 42 | 43 | // Receive packets from zero port. One queue will be added automatically. 44 | firstFlow, err := flow.SetReceiver(uint16(*inport)) 45 | flow.CheckFatal(err) 46 | 47 | // Separate packets for additional flow due to some rules 48 | secondFlow, err := flow.SetSeparator(firstFlow, l3Separator, nil) 49 | flow.CheckFatal(err) 50 | 51 | // Handle second flow via some heavy function 52 | flow.CheckFatal(flow.SetHandler(firstFlow, heavyFunc, nil)) 53 | 54 | // Send both flows each one to one port. Queues will be added automatically. 55 | flow.CheckFatal(flow.SetSender(firstFlow, uint16(*outport1))) 56 | flow.CheckFatal(flow.SetSender(secondFlow, uint16(*outport2))) 57 | 58 | flow.CheckFatal(flow.SystemStart()) 59 | } 60 | 61 | func l3Separator(currentPacket *packet.Packet, context flow.UserContext) bool { 62 | localL2Rules := l2Rules 63 | localL3Rules := l3Rules 64 | return currentPacket.L2ACLPermit(localL2Rules) && 65 | currentPacket.L3ACLPermit(localL3Rules) 66 | } 67 | 68 | func heavyFunc(currentPacket *packet.Packet, context flow.UserContext) { 69 | for i := uint(0); i < load; i++ { 70 | } 71 | } 72 | 73 | func updateSeparateRules() { 74 | for { 75 | time.Sleep(time.Second * 5) 76 | var err error 77 | l2Rules, err = packet.GetL2ACLFromJSON("demoL2_ACL.json") 78 | flow.CheckFatal(err) 79 | l3Rules, err = packet.GetL3ACLFromJSON("demoL3_ACL.json") 80 | flow.CheckFatal(err) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /examples/demo/demoL2_ACL.json: -------------------------------------------------------------------------------- 1 | { 2 | "L2Rules": [ 3 | { 4 | "Rule": "Accept", 5 | "Source": "ANY", 6 | "Destination": "ANY", 7 | "ID": "ANY" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /examples/demo/demoL3_ACL.json: -------------------------------------------------------------------------------- 1 | { 2 | "L3Rules": [ 3 | { 4 | "OutputNumber": "Accept", 5 | "SrcAddr": "111.2.0.0/31", 6 | "DstAddr": "ANY", 7 | "ID": "ANY", 8 | "SrcPort": "ANY", 9 | "DstPort": "ANY" 10 | }, 11 | { 12 | "OutputNumber": "Reject", 13 | "SrcAddr": "111.2.0.2/32", 14 | "DstAddr": "ANY", 15 | "ID": "ANY", 16 | "SrcPort": "ANY", 17 | "DstPort": "ANY" 18 | }, 19 | { 20 | "OutputNumber": "Accept", 21 | "SrcAddr": "ANY", 22 | "DstAddr": "ANY", 23 | "ID": "ANY", 24 | "SrcPort": "ANY", 25 | "DstPort": "ANY" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /examples/devbind.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "log" 6 | 7 | "github.com/intel-go/nff-go/devices" 8 | "github.com/intel-go/nff-go/flow" 9 | "github.com/intel-go/nff-go/packet" 10 | ) 11 | 12 | // Example that shows how to bind a driver to a NIC 13 | func main() { 14 | nic := flag.String("nic", "enp0s9", "network interface to run DPDK") 15 | bind := flag.String("bind", "igb_uio", "dpdk uio driver") 16 | flag.Parse() 17 | 18 | device, err := devices.New(*nic) 19 | flow.CheckFatal(err) 20 | 21 | driver, err := device.CurrentDriver() 22 | if err != nil { 23 | log.Println("Failed to get CurrentDriver:", err) 24 | return 25 | } 26 | 27 | defer func() { 28 | flow.SystemStop() 29 | 30 | // Re-Bind to original driver 31 | device.Bind(driver) 32 | }() 33 | 34 | // Bind to new user specified driver 35 | device.Bind(*bind) 36 | 37 | config := &flow.Config{ 38 | HWTXChecksum: true, 39 | } 40 | flow.SystemInit(config) 41 | 42 | var port uint16 = 0 43 | 44 | mainFlow, err := flow.SetReceiver(port) 45 | if err != nil { 46 | log.Println("Failed to SetReceiver:", err) 47 | return 48 | } 49 | 50 | err = flow.SetHandlerDrop(mainFlow, handler, nil) 51 | if err != nil { 52 | log.Println("Failed to SetHandlerDrop:", err) 53 | return 54 | } 55 | 56 | err = flow.SetSender(mainFlow, port) 57 | if err != nil { 58 | log.Println("Failed to SetSender:", err) 59 | return 60 | } 61 | 62 | err = flow.SystemStart() 63 | if err != nil { 64 | log.Println("Failed to SystemStart:", err) 65 | return 66 | } 67 | } 68 | 69 | func handler(*packet.Packet, flow.UserContext) bool { 70 | return true 71 | } 72 | -------------------------------------------------------------------------------- /examples/dpi/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | SUBDIRS = main pattern 7 | 8 | export GO_BUILD_TAGS += hyperscan_v4 9 | 10 | include $(PATH_TO_MK)/intermediate.mk 11 | -------------------------------------------------------------------------------- /examples/dpi/README.md: -------------------------------------------------------------------------------- 1 | For DPI example application gohs package is required. 2 | 3 | ## Build gohs 4 | 1. Install [Intel Hyperscan](https://github.com/intel/hyperscan.git) with your package manager. 5 | If hyperscan can not be installed from repo, first use [instruction](#Build-Hyperscan) below. 6 | 7 | 2. Download and build gohs package: 8 | 9 | go get -v github.com/flier/gohs/hyperscan 10 | 11 | 12 | ## Build Hyperscan 13 | 14 | 1. Download and build [Intel Hyperscan](https://github.com/intel/hyperscan.git) library. 15 | 16 | git clone https://github.com/intel/hyperscan.git 17 | cd hyperscan 18 | cmake . && make -j10 19 | 20 | 2. Set variables: 21 | 22 | HSDIR=/path/to/hyperscan 23 | export PKG_CONFIG_PATH=$HSDIR 24 | export CGO_LDFLAGS="-L$HSDIR/lib -lhs" 25 | export CGO_CFLAGS=-I$HSDIR/src 26 | 27 | -------------------------------------------------------------------------------- /examples/dpi/main/.gitignore: -------------------------------------------------------------------------------- 1 | dpi 2 | -------------------------------------------------------------------------------- /examples/dpi/main/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = dpi 7 | EXECUTABLES = dpi 8 | 9 | dpi: ../pattern gohs 10 | 11 | gohs: 12 | go get -tags hyperscan_v4 -v github.com/flier/gohs/hyperscan 13 | 14 | COMMON_FILES = handlers.go 15 | 16 | include $(PATH_TO_MK)/leaf.mk 17 | -------------------------------------------------------------------------------- /examples/dpi/main/patterns.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "AllowService", 4 | "regexp": "Host: [a-z-]*.service.com", 5 | "allow": true 6 | }, 7 | { 8 | "name": "AllowOtherService", 9 | "regexp": "Host: [0-9a-z.]*.otherservice.com", 10 | "allow": true 11 | }, 12 | { 13 | "name": "VideoDownl", 14 | "regexp": "Content-Type: video", 15 | "allow": true 16 | }, 17 | { 18 | "name": "GoodHTTP", 19 | "regexp": "Content-Type: (text/html|text/css|image)", 20 | "allow": true 21 | }, 22 | { 23 | "name": "BlockJavaScriptAppType", 24 | "regexp": "Content-Type: application/(x-|)javascript", 25 | "allow": false 26 | }, 27 | { 28 | "name": "BlockJavaScriptInHTML", 29 | "regexp": "((<[\\s\\/]*script\\b[^>]*>)([^>]*)(<\\/script>))", 30 | "allow": false 31 | } 32 | ] -------------------------------------------------------------------------------- /examples/dpi/pattern/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = dpi-pattern 7 | 8 | pattern: 9 | go install -tags hyperscan_v4 10 | -------------------------------------------------------------------------------- /examples/dpi/pattern/pattern.go: -------------------------------------------------------------------------------- 1 | package pattern 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "regexp" 9 | 10 | "github.com/flier/gohs/hyperscan" 11 | ) 12 | 13 | const ( 14 | // TotalNumFlows keeps last flow for dropped packets 15 | TotalNumFlows uint = 2 16 | // NumFlows = 1 is enough to process packets from file 17 | NumFlows uint = TotalNumFlows - 1 18 | ) 19 | 20 | // HSdb keeps Hyperscan db and scratches 21 | type HSdb struct { 22 | // Bdb is Hyperscan block database 23 | Bdb hyperscan.BlockDatabase 24 | // Scratches keep separate scratch for each handler 25 | Scratches [NumFlows]*hyperscan.Scratch 26 | } 27 | 28 | // Pattern describes one regex and action on match (allow/disallow packet) 29 | type Pattern struct { 30 | Name string 31 | Regexp string 32 | Re *regexp.Regexp 33 | Allow bool 34 | } 35 | 36 | // GetPatternsFromFile reads JSON file 37 | func GetPatternsFromFile(filename string) ([]Pattern, error) { 38 | f, err := ioutil.ReadFile(filename) 39 | if err != nil { 40 | return nil, err 41 | } 42 | patterns := make([]Pattern, 0) 43 | if err := json.Unmarshal(f, &patterns); err != nil { 44 | return nil, err 45 | } 46 | return patterns, nil 47 | } 48 | 49 | // SetupGoRegexps compiles each regexp in pattern array and keep result 50 | // in pattern.Re 51 | func SetupGoRegexps(patterns []Pattern) { 52 | for i := 0; i < len(patterns); i++ { 53 | patterns[i].Re = regexp.MustCompile(patterns[i].Regexp) 54 | } 55 | } 56 | 57 | // SetupHyperscan makes setup of Hyperscan DB and preallocates Scratches 58 | func (hsdb *HSdb) SetupHyperscan(patterns []Pattern) { 59 | unparsed := getAllowPatterns(patterns) 60 | parsed := parsePatterns(unparsed) 61 | var err error 62 | hsdb.Bdb, err = hyperscan.NewBlockDatabase(parsed...) 63 | if err != nil { 64 | fmt.Fprintf(os.Stderr, "ERROR: Could not compile patterns, %s", err) 65 | os.Exit(-1) 66 | } 67 | 68 | // Allocate one scratch per flow 69 | for i := uint(0); i < NumFlows; i++ { 70 | hsdb.Scratches[i], err = hyperscan.NewScratch(hsdb.Bdb) 71 | if err != nil { 72 | fmt.Fprintf(os.Stderr, "ERROR: Could sot allocate scratch space i=%d for block db: %s", i, err) 73 | os.Exit(-1) 74 | } 75 | } 76 | } 77 | 78 | // CleanupHyperscan close DB and deallocate Scratches 79 | func (hsdb *HSdb) CleanupHyperscan() { 80 | for i := uint(0); i < NumFlows; i++ { 81 | hsdb.Scratches[i].Free() 82 | } 83 | hsdb.Bdb.Close() 84 | } 85 | 86 | func getAllowPatterns(patterns []Pattern) (ret []string) { 87 | for _, p := range patterns { 88 | if p.Allow == true { 89 | ret = append(ret, p.Regexp) 90 | } 91 | } 92 | if len(ret) == 0 { 93 | fmt.Fprintf(os.Stderr, "ERROR: no 'allow' rules in file. HS mode support only allow rules") 94 | os.Exit(-1) 95 | } 96 | return 97 | } 98 | 99 | func parsePatterns(unparsed []string) (patterns []*hyperscan.Pattern) { 100 | for k, v := range unparsed { 101 | p, err := hyperscan.ParsePattern(v) 102 | if err != nil { 103 | fmt.Fprintf(os.Stderr, "ERROR: could not parse pattern: %s", err) 104 | os.Exit(-1) 105 | } 106 | p.Id = k 107 | patterns = append(patterns, p) 108 | } 109 | return 110 | } 111 | -------------------------------------------------------------------------------- /examples/dump.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | 11 | "github.com/intel-go/nff-go/flow" 12 | "github.com/intel-go/nff-go/packet" 13 | ) 14 | 15 | func main() { 16 | dumptype := flag.Uint("dumptype", 0, "dumping format type (0 - dumper function, 1 - hex, 2 - pcap file)") 17 | outport := flag.Uint("outport", 1, "port for sender") 18 | inport := flag.Uint("inport", 0, "port for receiver") 19 | flag.Parse() 20 | 21 | // Initialize NFF-GO library at 10 available cores 22 | config := flow.Config{ 23 | CPUList: "0-9", 24 | } 25 | flow.CheckFatal(flow.SystemInit(&config)) 26 | 27 | // Receive packets from zero port. One queue will be added automatically. 28 | firstFlow, err := flow.SetReceiver(uint16(*inport)) 29 | flow.CheckFatal(err) 30 | 31 | // Separate each 50000000th packet for dumping 32 | secondFlow, err := flow.SetPartitioner(firstFlow, 50000000, 1) 33 | flow.CheckFatal(err) 34 | 35 | // Dump separated packet. By default function dumper() is used. 36 | switch *dumptype { 37 | case 1: 38 | flow.CheckFatal(flow.SetHandler(secondFlow, hexdumper, nil)) 39 | case 2: 40 | // Writer closes flow 41 | flow.CheckFatal(flow.SetSenderFile(secondFlow, "out.pcap")) 42 | default: 43 | flow.CheckFatal(flow.SetHandler(secondFlow, dumper, nil)) 44 | } 45 | 46 | // All cases except SetSenderFile require to merge partitioned packets to original flow 47 | var output *flow.Flow 48 | if *dumptype == 2 { 49 | output = firstFlow 50 | } else { 51 | output, err = flow.SetMerger(firstFlow, secondFlow) 52 | flow.CheckFatal(err) 53 | } 54 | flow.CheckFatal(flow.SetSender(output, uint16(*outport))) 55 | 56 | flow.CheckFatal(flow.SystemStart()) 57 | } 58 | 59 | func dumper(currentPacket *packet.Packet, context flow.UserContext) { 60 | var tcp *packet.TCPHdr 61 | var udp *packet.UDPHdr 62 | var icmp *packet.ICMPHdr 63 | 64 | fmt.Printf("%v", currentPacket.Ether) 65 | ipv4, ipv6, arp := currentPacket.ParseAllKnownL3() 66 | if ipv4 != nil { 67 | fmt.Printf("%v", ipv4) 68 | tcp, udp, icmp = currentPacket.ParseAllKnownL4ForIPv4() 69 | } else if ipv6 != nil { 70 | fmt.Printf("%v", ipv6) 71 | tcp, udp, icmp = currentPacket.ParseAllKnownL4ForIPv6() 72 | } else if arp != nil { 73 | fmt.Printf("%v", arp) 74 | } else { 75 | fmt.Println(" Unknown L3 protocol") 76 | } 77 | 78 | if tcp != nil { 79 | fmt.Printf("%v", tcp) 80 | } else if udp != nil { 81 | fmt.Printf("%v", udp) 82 | } else if icmp != nil { 83 | fmt.Printf("%v", icmp) 84 | } else { 85 | fmt.Println(" Unknown L4 protocol") 86 | } 87 | fmt.Println("----------------------------------------------------------") 88 | } 89 | 90 | func hexdumper(currentPacket *packet.Packet, context flow.UserContext) { 91 | fmt.Printf("Raw bytes=%x\n", currentPacket.GetRawPacketBytes()) 92 | } 93 | -------------------------------------------------------------------------------- /examples/fileReadWrite/.gitignore: -------------------------------------------------------------------------------- 1 | fileReadWrite -------------------------------------------------------------------------------- /examples/fileReadWrite/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | 12 | COPY fileReadWrite . 13 | COPY fileReadWriteIn.pcap . 14 | -------------------------------------------------------------------------------- /examples/fileReadWrite/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | IMAGENAME = nff-go-example-file-rw 7 | EXECUTABLES = fileReadWrite 8 | 9 | include $(PATH_TO_MK)/leaf.mk 10 | -------------------------------------------------------------------------------- /examples/fileReadWrite/fileReadWrite.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | ) 13 | 14 | func main() { 15 | inFile := flag.String("infile", "fileReadWriteIn.pcap", "Input pcap file") 16 | outFile := flag.String("outfile", "fileReadWriteOut.pcap", "Output pcap file") 17 | 18 | useReader := flag.Bool("reader", false, "Enable Reader") 19 | useWriter := flag.Bool("writer", false, "Enable Writer") 20 | 21 | repcount := flag.Int("repcnt", 1, "Number of times for reader to read infile") 22 | outport := flag.Uint("outport", 0, "Port for sender") 23 | flag.Parse() 24 | 25 | // Initialize NFF-GO library at 16 cores by default 26 | config := flow.Config{ 27 | CPUList: "0-15", 28 | } 29 | flow.CheckFatal(flow.SystemInit(&config)) 30 | 31 | var f1 *flow.Flow 32 | if *useReader { 33 | print("Enabled Read from file ", *inFile, " and ") 34 | f1 = flow.SetReceiverFile(*inFile, int32(*repcount)) 35 | } else { 36 | print("Enabled Generate and ") 37 | f1 = flow.SetGenerator(generatePacket, nil) 38 | } 39 | 40 | if *useWriter { 41 | println("Write to file", *outFile) 42 | flow.CheckFatal(flow.SetSenderFile(f1, *outFile)) 43 | } else { 44 | println("Send to port", outport) 45 | flow.CheckFatal(flow.SetSender(f1, uint16(*outport))) 46 | } 47 | 48 | flow.CheckFatal(flow.SystemStart()) 49 | } 50 | 51 | func generatePacket(pkt *packet.Packet, context flow.UserContext) { 52 | // Total packet size will be 14+20+20+70+4(crc)=128 bytes 53 | if packet.InitEmptyPacket(pkt, 70) == true { 54 | pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55} 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/fileReadWrite/fileReadWriteIn.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aregm/nff-go/3fcc11eab4030598949f7e34be99ed8f70221e08/examples/fileReadWrite/fileReadWriteIn.pcap -------------------------------------------------------------------------------- /examples/firewall/.gitignore: -------------------------------------------------------------------------------- 1 | firewall -------------------------------------------------------------------------------- /examples/firewall/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | 12 | COPY firewall . 13 | COPY firewall.conf . 14 | -------------------------------------------------------------------------------- /examples/firewall/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | IMAGENAME = nff-go-example-firewall 7 | EXECUTABLES = firewall 8 | 9 | include $(PATH_TO_MK)/leaf.mk 10 | -------------------------------------------------------------------------------- /examples/firewall/firewall.conf: -------------------------------------------------------------------------------- 1 | # This file is used in "Firewall.go" example. It accepts some packets and drops others 2 | 3 | # Source address, Destination address, L4 protocol ID, Source port, Destination port, Decision 4 | 10.10.0.5/24 ANY TCP 46 ANY Accept 5 | 111.2.0.4/32 ANY TCP 49:122 ANY Accept 6 | ANY 21.23.45.10/32 UDP ANY ANY Accept 7 | ANY ANY UDP ANY 4080 Accept 8 | 9 | # Other tuples are rejected 10 | -------------------------------------------------------------------------------- /examples/firewall/firewall.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | ) 13 | 14 | var ( 15 | l3Rules *packet.L3Rules 16 | ) 17 | 18 | // Main function for constructing packet processing graph. 19 | func main() { 20 | var err error 21 | outport := flag.Uint("outport", 1, "port for sender") 22 | inport := flag.Uint("inport", 0, "port for receiver") 23 | flag.Parse() 24 | 25 | // Initialize NFF-GO library at 8 cores by default 26 | config := flow.Config{ 27 | CPUList: "0-7", 28 | } 29 | flow.CheckFatal(flow.SystemInit(&config)) 30 | 31 | // Get filtering rules from access control file. 32 | l3Rules, err = packet.GetL3ACLFromTextTable("firewall.conf") 33 | flow.CheckFatal(err) 34 | 35 | // Receive packets from zero port. Receive queue will be added automatically. 36 | inputFlow, err := flow.SetReceiver(uint16(*inport)) 37 | flow.CheckFatal(err) 38 | 39 | // Separate packet flow based on ACL. 40 | rejectFlow, err := flow.SetSeparator(inputFlow, l3Separator, nil) 41 | flow.CheckFatal(err) 42 | 43 | // Drop rejected packets. 44 | flow.CheckFatal(flow.SetStopper(rejectFlow)) 45 | 46 | // Send accepted packets to first port. Send queue will be added automatically. 47 | flow.CheckFatal(flow.SetSender(inputFlow, uint16(*outport))) 48 | 49 | // Begin to process packets. 50 | flow.CheckFatal(flow.SystemStart()) 51 | } 52 | 53 | // User defined function for separating packets 54 | func l3Separator(currentPacket *packet.Packet, context flow.UserContext) bool { 55 | // Return whether packet is accepted or not. Based on ACL rules. 56 | return currentPacket.L3ACLPermit(l3Rules) 57 | } 58 | -------------------------------------------------------------------------------- /examples/forwarding/.gitignore: -------------------------------------------------------------------------------- 1 | forwarding -------------------------------------------------------------------------------- /examples/forwarding/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | 12 | COPY forwarding . 13 | COPY forwarding.conf . 14 | -------------------------------------------------------------------------------- /examples/forwarding/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | IMAGENAME = nff-go-example-forwarding 7 | EXECUTABLES = forwarding 8 | 9 | include $(PATH_TO_MK)/leaf.mk 10 | -------------------------------------------------------------------------------- /examples/forwarding/forwarding.conf: -------------------------------------------------------------------------------- 1 | # This file is used in "Forwarding.go" example. It divides packets to four flows and drop some of them 2 | 3 | # Source address, Destination address, L4 protocol ID, Source port, Destination port, Output port 4 | 111.2.0.0/31 ANY tcp ANY ANY 2 5 | 111.2.0.2/32 ANY tcp ANY ANY Reject 6 | 111.2.0.4/32 ANY tcp 10:19 ANY 2 7 | 111.2.0.4/32 ANY tcp 20:29 ANY 3 8 | ANY ANY udp ANY ANY 1 9 | 111.2.0.5/32 ANY tcp 20:29 ANY 10 | ANY ANY udp 3078:3964 56:61020 4 11 | -------------------------------------------------------------------------------- /examples/forwarding/forwarding.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "net" 10 | 11 | "github.com/intel-go/nff-go/flow" 12 | "github.com/intel-go/nff-go/packet" 13 | ) 14 | 15 | var l3Rules *packet.L3Rules 16 | 17 | // Main function for constructing packet processing graph. 18 | func main() { 19 | inport := flag.Uint("inport", 0, "Port for receiving packets.") 20 | numflows := flag.Uint("numflows", 5, "Number of output flows to use. First flow with number zero is used for dropped packets.") 21 | nostats := flag.Bool("nostats", false, "Disable statics HTTP server.") 22 | flag.Parse() 23 | 24 | var err error 25 | var statsServerAddres *net.TCPAddr = nil 26 | if !*nostats { 27 | // Set up address for stats web server 28 | statsServerAddres = &net.TCPAddr{ 29 | Port: 8080, 30 | } 31 | } 32 | 33 | // Initialize NFF-GO library at 16 cores by default 34 | config := flow.Config{ 35 | StatsHTTPAddress: statsServerAddres, 36 | } 37 | flow.CheckFatal(flow.SystemInit(&config)) 38 | 39 | // Get splitting rules from access control file. 40 | l3Rules, err = packet.GetL3ACLFromTextTable("forwarding.conf") 41 | flow.CheckFatal(err) 42 | 43 | // Receive packets from zero port. Receive queue will be added automatically. 44 | inputFlow, err := flow.SetReceiver(uint16(*inport)) 45 | flow.CheckFatal(err) 46 | 47 | // Split packet flow based on ACL. 48 | flowsNumber := uint16(*numflows) 49 | outputFlows, err := flow.SetSplitter(inputFlow, l3Splitter, uint(flowsNumber), nil) 50 | flow.CheckFatal(err) 51 | 52 | // "0" flow is used for dropping packets without sending them. 53 | flow.CheckFatal(flow.SetStopper(outputFlows[0])) 54 | 55 | // Send each flow to corresponding port. Send queues will be added automatically. 56 | for i := uint16(1); i < flowsNumber; i++ { 57 | flow.CheckFatal(flow.SetSender(outputFlows[i], i-1)) 58 | } 59 | 60 | // Begin to process packets. 61 | flow.CheckFatal(flow.SystemStart()) 62 | } 63 | 64 | // User defined function for splitting packets 65 | func l3Splitter(currentPacket *packet.Packet, context flow.UserContext) uint { 66 | // Return number of flow to which put this packet. Based on ACL rules. 67 | return currentPacket.L3ACLPort(l3Rules) 68 | } 69 | -------------------------------------------------------------------------------- /examples/generate.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | "time" 13 | ) 14 | 15 | func main() { 16 | 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.") 17 | output := flag.Int("port", 1, "output port") 18 | flag.Parse() 19 | outputPort := uint16(*output) 20 | 21 | flow.SystemInit(nil) 22 | 23 | switch *mode { 24 | case 0: 25 | firstFlow, genChannel, _ := flow.SetFastGenerator(generatePacket, 3500, nil) 26 | flow.CheckFatal(flow.SetSender(firstFlow, outputPort)) 27 | go updateSpeed(genChannel) 28 | flow.SystemStart() 29 | case 1: 30 | firstFlow := flow.SetGenerator(generatePacket1, nil) 31 | flow.CheckFatal(flow.SetSender(firstFlow, outputPort)) 32 | flow.SystemStart() 33 | case 2: 34 | temp, _ := (flow.SetReceiver(outputPort)) 35 | flow.SetStopper(temp) 36 | flow.SystemInitPortsAndMemory() 37 | generatePacket2(outputPort) 38 | } 39 | } 40 | 41 | func generatePacket(pkt *packet.Packet, context flow.UserContext) { 42 | packet.InitEmptyIPv4Packet(pkt, 1300) 43 | pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55} 44 | } 45 | 46 | func generatePacket1(pkt *packet.Packet, context flow.UserContext) { 47 | packet.InitEmptyIPv4Packet(pkt, 1300) 48 | pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55} 49 | time.Sleep(175 * time.Microsecond) 50 | } 51 | 52 | func generatePacket2(port uint16) { 53 | for { 54 | pkt, _ := packet.NewPacket() 55 | packet.InitEmptyIPv4Packet(pkt, 1300) 56 | pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55} 57 | pkt.SendPacket(port) 58 | time.Sleep(175 * time.Microsecond) 59 | } 60 | } 61 | 62 | func updateSpeed(genChannel chan uint64) { 63 | var load int 64 | for { 65 | // Can be file or any other source 66 | if _, err := fmt.Scanf("%d", &load); err == nil { 67 | genChannel <- uint64(load) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /examples/ipsec/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | SUBDIRS = stability perf 7 | 8 | include $(PATH_TO_MK)/intermediate.mk 9 | -------------------------------------------------------------------------------- /examples/ipsec/crypto_mb/aes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crypto_mb 6 | 7 | //TODO check cpuid 8 | 9 | type aes_x8 struct { 10 | blockSize int 11 | enc []uint32 12 | dec []uint32 13 | } 14 | 15 | func (this *aes_x8) BlockSize() int { 16 | return this.blockSize 17 | } 18 | 19 | func (this *aes_x8) VecSize() int { 20 | return 8 21 | } 22 | 23 | //TODO accept number of blocks 24 | func NewAESMultiBlock(key []byte) MultiBlock { 25 | if len(key) != 16 { 26 | // TODO return error? 27 | panic("For now only 16-byte keys are supported") 28 | } 29 | n := len(key) + 28 30 | rounds := 10 31 | c := aes_x8{len(key), make([]uint32, n), make([]uint32, n)} 32 | expandKeyAsm(rounds, &key[0], &c.enc[0], &c.dec[0]) 33 | return &c 34 | } 35 | 36 | // in aes.s 37 | //go:noescape 38 | func encrypt8BlocksAsm(xk *uint32, dst, src [][]byte) 39 | 40 | func (this *aes_x8) DecryptMany(dst, src [][]byte) { 41 | panic("Not implemented yet") 42 | } 43 | -------------------------------------------------------------------------------- /examples/ipsec/crypto_mb/aes_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crypto_mb 6 | 7 | import "testing" 8 | 9 | //TODO Separate test package? 10 | 11 | // Appendix B, C of FIPS 197: Cipher examples, Example vectors. 12 | type CryptTest struct { 13 | key []byte 14 | in []byte 15 | out []byte 16 | } 17 | 18 | var encryptTests = []CryptTest{ 19 | { 20 | // Appendix B. 21 | []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}, 22 | []byte{0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34}, 23 | []byte{0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32}, 24 | }, 25 | { 26 | // Appendix C.1. AES-128 27 | []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, 28 | []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, 29 | []byte{0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a}, 30 | }, 31 | } 32 | 33 | // Test Cipher Encrypt method against FIPS 197 examples. 34 | func TestCipherEncrypt(t *testing.T) { 35 | for i, tt := range encryptTests { 36 | c := NewAESMultiBlock(tt.key) 37 | out := make([][]byte, 0) 38 | in := make([][]byte, 0) 39 | for i := 0; i < c.VecSize(); i++ { 40 | in = append(in, tt.in) 41 | out = append(out, make([]byte, len(tt.in))) 42 | } 43 | c.EncryptMany(out, in) 44 | for s := 0; s < c.VecSize(); s++ { 45 | for j, v := range out[s] { 46 | if v != tt.out[j] { 47 | t.Errorf("EncryptMany slice %d %d: out[%d] = %#x, want %#x", s, i, j, v, tt.out[j]) 48 | break 49 | } 50 | } 51 | } 52 | } 53 | } 54 | 55 | func BenchmarkEncrypt(b *testing.B) { 56 | tt := encryptTests[0] 57 | c := NewAESMultiBlock(tt.key) 58 | out := make([][]byte, 0) 59 | in := make([][]byte, 0) 60 | for i := 0; i < c.VecSize(); i++ { 61 | in = append(in, tt.in) 62 | out = append(out, make([]byte, len(tt.in))) 63 | } 64 | b.SetBytes(int64(len(out[0]) * c.VecSize())) 65 | b.ResetTimer() 66 | for i := 0; i < b.N; i++ { 67 | c.EncryptMany(out, in) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /examples/ipsec/crypto_mb/expandKeyAsm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crypto_mb 6 | 7 | // in aes.s 8 | //go:noescape 9 | func expandKeyAsm(nr int, key *byte, enc, dec *uint32) 10 | -------------------------------------------------------------------------------- /examples/ipsec/crypto_mb/hmac.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package crypto_mb 6 | 7 | //based on crypto/hmac 8 | // key is zero padded to the block size of the hash function 9 | // ipad = 0x36 byte repeated for key length 10 | // opad = 0x5c byte repeated for key length 11 | // hmac = H([key ^ opad] H([key ^ ipad] text)) 12 | 13 | type multihmac struct { 14 | size int 15 | blocksize int 16 | vecsize int 17 | opad, ipad [][]byte 18 | outer, inner MultiHash 19 | p1, p2 [][]byte 20 | } 21 | 22 | func (h *multihmac) Sum(in [][]byte) [][]byte { 23 | origLen := 0 24 | if len(in) != 0 { 25 | origLen = len(in[0]) 26 | } 27 | //TODO fix,check len(in) 28 | in = h.inner.Sum(in) 29 | h.outer.Reset() 30 | h.outer.Write(h.opad) 31 | for i := range h.p1 { 32 | h.p1[i] = in[i][origLen:] 33 | h.p2[i] = in[i][:origLen] 34 | } 35 | h.outer.Write(h.p1) 36 | return h.outer.Sum(h.p2) 37 | } 38 | 39 | // Doesn't implement io.writer due to input 40 | func (h *multihmac) Write(p [][]byte) int { 41 | return h.inner.Write(p) 42 | } 43 | 44 | func (h *multihmac) Size() int { return h.size } 45 | 46 | func (h *multihmac) BlockSize() int { return h.blocksize } 47 | 48 | func (h *multihmac) VecSize() int { return h.vecsize } 49 | 50 | func (h *multihmac) Reset() { 51 | h.inner.Reset() 52 | h.inner.Write(h.ipad) 53 | } 54 | 55 | //TODO separate packages to avoid name collisions 56 | // New returns a new HMAC hash using the given hash.Hash type and key. 57 | func NewHmac(h func() MultiHash, key []byte) MultiHash { 58 | hm := new(multihmac) 59 | hm.outer = h() 60 | hm.inner = h() 61 | hm.size = hm.inner.Size() 62 | hm.vecsize = hm.inner.VecSize() 63 | hm.blocksize = hm.inner.BlockSize() 64 | hm.ipad = make([][]byte, hm.vecsize) 65 | hm.opad = make([][]byte, hm.vecsize) 66 | hm.p1 = make([][]byte, hm.vecsize) 67 | hm.p2 = make([][]byte, hm.vecsize) 68 | keys := make([][]byte, hm.vecsize) 69 | for i := range hm.ipad { 70 | hm.ipad[i] = make([]byte, hm.blocksize) 71 | hm.opad[i] = make([]byte, hm.blocksize) 72 | keys[i] = make([]byte, len(key)) 73 | copy(keys[i], key) 74 | } 75 | // println(keys[0]) 76 | if len(key) > hm.blocksize { 77 | // If key is too big, hash it. 78 | hm.outer.Write(keys) 79 | keys = hm.outer.Sum(nil) 80 | // println(keys[0]) 81 | } 82 | for i := 0; i < hm.vecsize; i++ { 83 | copy(hm.ipad[i], keys[i]) 84 | copy(hm.opad[i], keys[i]) 85 | for j := range hm.ipad[i] { 86 | hm.ipad[i][j] ^= 0x36 87 | } 88 | for j := range hm.opad[i] { 89 | hm.opad[i][j] ^= 0x5c 90 | } 91 | } 92 | hm.inner.Write(hm.ipad) 93 | return hm 94 | } 95 | -------------------------------------------------------------------------------- /examples/ipsec/perf/.gitignore: -------------------------------------------------------------------------------- 1 | ipsec 2 | -------------------------------------------------------------------------------- /examples/ipsec/perf/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY ipsec . 12 | -------------------------------------------------------------------------------- /examples/ipsec/perf/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = nff-go-ipsec-perf 7 | EXECUTABLES = ipsec 8 | include $(PATH_TO_MK)/leaf.mk 9 | -------------------------------------------------------------------------------- /examples/ipsec/perf/ipsec.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/intel-go/nff-go/examples/ipsec" 8 | import "github.com/intel-go/nff-go/flow" 9 | import "flag" 10 | 11 | func main() { 12 | outport := flag.Uint("outport", 1, "port for sender") 13 | inport := flag.Uint("inport", 0, "port for receiver") 14 | noscheduler := flag.Bool("no-scheduler", false, "disable scheduler") 15 | dpdkLogLevel := flag.String("dpdk", "--log-level=0", "Passes an arbitrary argument to dpdk EAL") 16 | cores := flag.String("cores", "0-10", "Cores mask. Avoid hyperthreading here") 17 | vector := flag.Bool("v", false, "vector version") 18 | dec := flag.Bool("d", false, "decapsulate after encapsulation") 19 | 20 | flag.Parse() 21 | 22 | config := flow.Config{ 23 | DisableScheduler: *noscheduler, 24 | DPDKArgs: []string{*dpdkLogLevel}, 25 | CPUList: *cores, 26 | } 27 | flow.SystemInit(&config) 28 | input, _ := flow.SetReceiver(uint16(*inport)) 29 | if *vector { 30 | flow.SetVectorHandlerDrop(input, ipsec.VectorEncapsulation, ipsec.VContext{}) 31 | } else { 32 | flow.SetHandlerDrop(input, ipsec.ScalarEncapsulation, ipsec.SContext{}) 33 | } 34 | if *dec { 35 | flow.SetHandlerDrop(input, ipsec.Decapsulation, ipsec.SContext{}) 36 | } 37 | flow.SetSender(input, uint16(*outport)) 38 | flow.SystemStart() 39 | } 40 | -------------------------------------------------------------------------------- /examples/ipsec/stability/.gitignore: -------------------------------------------------------------------------------- 1 | stability 2 | -------------------------------------------------------------------------------- /examples/ipsec/stability/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY stability . 12 | -------------------------------------------------------------------------------- /examples/ipsec/stability/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = nff-go-ipsec-stability 7 | EXECUTABLES = stability 8 | include $(PATH_TO_MK)/leaf.mk 9 | -------------------------------------------------------------------------------- /examples/ipsec/stability/stability.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/intel-go/nff-go/types" 8 | import "github.com/intel-go/nff-go/flow" 9 | import "github.com/intel-go/nff-go/packet" 10 | import "github.com/intel-go/nff-go/examples/ipsec" 11 | import "flag" 12 | import "fmt" 13 | import "time" 14 | 15 | var step int 16 | 17 | func main() { 18 | vector := flag.Bool("v", false, "vector version") 19 | mode := flag.Bool("m", false, "check encapsulation") 20 | flag.Parse() 21 | 22 | config := flow.Config{ 23 | DisableScheduler: true, 24 | } 25 | flow.SystemInit(&config) 26 | 27 | var input *flow.Flow 28 | gen := flow.SetGenerator(gen, nil) 29 | flow.SetHandler(gen, dump_before, nil) 30 | if *mode { 31 | if *vector { 32 | flow.SetVectorHandlerDrop(gen, ipsec.VectorEncapsulation, ipsec.VContext{}) 33 | } else { 34 | flow.SetHandlerDrop(gen, ipsec.ScalarEncapsulation, ipsec.SContext{}) 35 | } 36 | flow.SetSender(gen, 1) 37 | input, _ = flow.SetReceiver(0) 38 | } else { 39 | flow.SetSender(gen, 0) 40 | input, _ = flow.SetReceiver(1) 41 | flow.SetHandlerDrop(input, ipsec.Decapsulation, ipsec.SContext{}) 42 | } 43 | flow.SetHandler(input, dump_after, nil) 44 | flow.SetStopper(input) 45 | flow.SystemStart() 46 | } 47 | 48 | func gen(pkt *packet.Packet, context flow.UserContext) { 49 | packet.InitEmptyIPv4TCPPacket(pkt, 50) 50 | ipv4 := pkt.GetIPv4() 51 | tcp := pkt.GetTCPForIPv4() 52 | 53 | pkt.Ether.DAddr = [6]uint8{1, 2, 3, 4, 5, 6} 54 | pkt.Ether.SAddr = [6]uint8{1, 2, 3, 4, 5, 6} 55 | 56 | ipv4.SrcAddr = types.BytesToIPv4(111, 111, 111, 111) 57 | ipv4.DstAddr = types.BytesToIPv4(222, 222, 222, 222) 58 | 59 | tcp.SrcPort = packet.SwapBytesUint16(25) 60 | tcp.DstPort = packet.SwapBytesUint16(35) 61 | 62 | step++ 63 | if step == 100 { 64 | time.Sleep(100 * time.Millisecond) 65 | step = 0 66 | } 67 | } 68 | 69 | func dump_before(currentPacket *packet.Packet, context flow.UserContext) { 70 | fmt.Printf("Raw bytes before=%x\n", currentPacket.GetRawPacketBytes()) 71 | } 72 | 73 | func dump_after(currentPacket *packet.Packet, context flow.UserContext) { 74 | fmt.Printf("Raw bytes after =%x\n", currentPacket.GetRawPacketBytes()) 75 | } 76 | -------------------------------------------------------------------------------- /examples/ipsec/stability/test.conf: -------------------------------------------------------------------------------- 1 | sp ipv4 out esp protect 1234 pri 1 dst 222.222.222.0/24 sport 0:65535 dport 0:65535 2 | sa out 1234 cipher_algo aes-128-cbc cipher_key 41:45:53:31:32:38:4b:65:79:2d:31:36:43:68:61:72 \ 3 | auth_algo sha1-hmac auth_key 71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71 \ 4 | mode ipv4-tunnel src 111.22.3.0 dst 3.22.111.0 5 | rt ipv4 dst 3.22.111.0/24 port 1 6 | 7 | sa in 1234 cipher_algo aes-128-cbc cipher_key 41:45:53:31:32:38:4b:65:79:2d:31:36:43:68:61:72 \ 8 | auth_algo sha1-hmac auth_key 71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71:71 \ 9 | mode ipv4-tunnel src 111.22.3.0 dst 3.22.111.0 10 | rt ipv4 dst 222.222.222.222/24 port 0 11 | -------------------------------------------------------------------------------- /examples/ipsec/stability/test.sh: -------------------------------------------------------------------------------- 1 | # instruction for crypt library in DPDK: https://doc.dpdk.org/guides/cryptodevs/aesni_mb.html 2 | # instruction for ipsec application: https://doc.dpdk.org/guides/sample_app_ug/ipsec_secgw.html 3 | ./build/ipsec-secgw -l 4,5 -n 4 --socket-mem 0,1024 --vdev "crypto_aesni_mb" -- -p 0xf -P -u 0x2 --config="(0,0,4),(1,0,5)" -f test.conf 4 | -------------------------------------------------------------------------------- /examples/kni.go: -------------------------------------------------------------------------------- 1 | // For forwarding testing call 2 | // "insmod ./x86_64-native-linuxapp-gcc/kmod/rte_kni.ko lo_mode=lo_mode_fifo_skb" 3 | // from DPDK directory before compiling this test. It will make a loop of packets 4 | // inside KNI device and receive from KNI will receive all packets that were sent to KNI. 5 | 6 | // For ping testing call 7 | // "insmod ./x86_64-native-linuxapp-gcc/kmod/rte_kni.ko" 8 | // from DPDK directory before compiling this test. Use --ping option. 9 | 10 | // Other variants of rte_kni.ko configuration can be found here: 11 | // http://dpdk.org/doc/guides/sample_app_ug/kernel_nic_interface.html 12 | 13 | // Need to call "ifconfig myKNI 111.111.11.11" while running this example to allow other applications 14 | // to receive packets from "111.111.11.11" address 15 | 16 | package main 17 | 18 | import ( 19 | "flag" 20 | 21 | "github.com/intel-go/nff-go/flow" 22 | "github.com/intel-go/nff-go/packet" 23 | "github.com/intel-go/nff-go/types" 24 | ) 25 | 26 | var ping bool 27 | 28 | func main() { 29 | inport := flag.Uint("inport", 0, "port for receiver") 30 | outport := flag.Uint("outport", 0, "port for sender") 31 | kniport := flag.Uint("kniport", 0, "port for kni") 32 | mode := flag.Uint("mode", 0, "0 - for three cores for KNI send/receive/Linux, 1 - for single core for KNI send/receive, 2 - for one core for all KNI") 33 | flag.BoolVar(&ping, "ping", false, "use this for pushing only ARP and ICMP packets to KNI") 34 | flag.Parse() 35 | 36 | config := flow.Config{ 37 | // Is required for KNI 38 | NeedKNI: true, 39 | CPUList: "0-7", 40 | } 41 | 42 | flow.CheckFatal(flow.SystemInit(&config)) 43 | // port of device, name of device 44 | kni, err := flow.CreateKniDevice(uint16(*kniport), "myKNI") 45 | flow.CheckFatal(err) 46 | 47 | inputFlow, err := flow.SetReceiver(uint16(*inport)) 48 | flow.CheckFatal(err) 49 | 50 | toKNIFlow, err := flow.SetSeparator(inputFlow, pingSeparator, nil) 51 | flow.CheckFatal(err) 52 | 53 | var fromKNIFlow *flow.Flow 54 | switch *mode { 55 | case 0: 56 | flow.CheckFatal(flow.SetSenderKNI(toKNIFlow, kni)) 57 | fromKNIFlow = flow.SetReceiverKNI(kni) 58 | case 1: 59 | fromKNIFlow, err = flow.SetSenderReceiverKNI(toKNIFlow, kni, false) 60 | flow.CheckFatal(err) 61 | case 2: 62 | fromKNIFlow, err = flow.SetSenderReceiverKNI(toKNIFlow, kni, true) 63 | flow.CheckFatal(err) 64 | } 65 | 66 | outputFlow, err := flow.SetMerger(inputFlow, fromKNIFlow) 67 | flow.CheckFatal(err) 68 | flow.CheckFatal(flow.SetSender(outputFlow, uint16(*outport))) 69 | 70 | flow.CheckFatal(flow.SystemStart()) 71 | } 72 | 73 | func pingSeparator(current *packet.Packet, ctx flow.UserContext) bool { 74 | if ping == false { 75 | // All packets will go to KNI. 76 | // You should use lo_mode=lo_mode_fifo_skb for looping back these packets. 77 | return false 78 | } 79 | ipv4, ipv6, arp := current.ParseAllKnownL3() 80 | if arp != nil { 81 | return false 82 | } else if ipv4 != nil { 83 | if ipv4.NextProtoID == types.ICMPNumber { 84 | return false 85 | } 86 | } else if ipv6 != nil { 87 | if ipv6.Proto == types.ICMPNumber { 88 | return false 89 | } 90 | } 91 | return true 92 | } 93 | -------------------------------------------------------------------------------- /examples/lb/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | SUBDIRS = main 7 | 8 | include $(PATH_TO_MK)/intermediate.mk 9 | -------------------------------------------------------------------------------- /examples/lb/config.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package lb 6 | 7 | import ( 8 | "encoding/json" 9 | "os" 10 | 11 | "github.com/intel-go/nff-go/flow" 12 | "github.com/intel-go/nff-go/packet" 13 | "github.com/intel-go/nff-go/types" 14 | ) 15 | 16 | type NetworkSubnet struct { 17 | IPv4 types.IPv4Subnet `json:"ipv4"` 18 | IPv6 types.IPv6Subnet `json:"ipv6"` 19 | } 20 | 21 | type IpPort struct { 22 | Index uint16 `json:"index"` 23 | Subnet NetworkSubnet `json:"subnet"` 24 | neighCache *packet.NeighboursLookupTable 25 | macAddress types.MACAddress 26 | } 27 | 28 | type LoadBalancerConfig struct { 29 | InputPort IpPort `json:"input-port"` 30 | TunnelPort IpPort `json:"tunnel-port"` 31 | TunnelSubnet NetworkSubnet `json:"tunnel-subnet"` 32 | WorkerAddresses []types.IPv4Address `json:"worker-addresses"` 33 | } 34 | 35 | var LBConfig LoadBalancerConfig 36 | 37 | func ReadConfig(fileName string) error { 38 | file, err := os.Open(fileName) 39 | if err != nil { 40 | return err 41 | } 42 | decoder := json.NewDecoder(file) 43 | 44 | err = decoder.Decode(&LBConfig) 45 | if err != nil { 46 | return err 47 | } 48 | 49 | return nil 50 | } 51 | 52 | func InitFlows() { 53 | ioFlow, err := flow.SetReceiver(LBConfig.InputPort.Index) 54 | flow.CheckFatal(err) 55 | flow.CheckFatal(flow.SetHandlerDrop(ioFlow, balancer, nil)) 56 | flow.CheckFatal(flow.SetSender(ioFlow, LBConfig.TunnelPort.Index)) 57 | ioFlow, err = flow.SetReceiver(LBConfig.TunnelPort.Index) 58 | flow.CheckFatal(flow.SetHandlerDrop(ioFlow, arpHandler, nil)) 59 | flow.CheckFatal(flow.SetStopper(ioFlow)) 60 | 61 | LBConfig.InputPort.initPort() 62 | LBConfig.TunnelPort.initPort() 63 | } 64 | 65 | func (port *IpPort) initPort() { 66 | port.macAddress = flow.GetPortMACAddress(port.Index) 67 | port.neighCache = packet.NewNeighbourTable(port.Index, port.macAddress, 68 | func(ipv4 types.IPv4Address) bool { 69 | return ipv4 == port.Subnet.IPv4.Addr 70 | }, 71 | func(ipv6 types.IPv6Address) bool { 72 | return ipv6 == port.Subnet.IPv6.Addr 73 | }) 74 | } 75 | -------------------------------------------------------------------------------- /examples/lb/main/.gitignore: -------------------------------------------------------------------------------- 1 | lb 2 | -------------------------------------------------------------------------------- /examples/lb/main/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | 12 | COPY lb . 13 | COPY config.json . 14 | -------------------------------------------------------------------------------- /examples/lb/main/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = lb 7 | EXECUTABLES = lb 8 | 9 | lb: lb.go ../config.go 10 | 11 | include $(PATH_TO_MK)/leaf.mk 12 | -------------------------------------------------------------------------------- /examples/lb/main/config-aws.json: -------------------------------------------------------------------------------- 1 | { 2 | "input-port": { 3 | "index": 0, 4 | "subnet": { 5 | "ipv4": "10.0.14.10/24", 6 | "ipv6": "2600:1f16:80:ad14::10/64" 7 | } 8 | }, 9 | "tunnel-port": { 10 | "index": 1, 11 | "subnet": { 12 | "ipv4": "10.0.16.10/24", 13 | "ipv6": "2600:1f16:80:ad16::10/64" 14 | } 15 | }, 16 | "tunnel-subnet": { 17 | "ipv4": "10.0.18.0/24", 18 | "ipv6": "2600:1f16:80:ad18::/64" 19 | }, 20 | "worker-addresses": [ 21 | "10.0.16.20", 22 | "10.0.16.30" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /examples/lb/main/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "input-port": { 3 | "index": 0, 4 | "subnet": { 5 | "ipv4": "192.168.14.1/24", 6 | "ipv6": "fd14::1/64" 7 | } 8 | }, 9 | "tunnel-port": { 10 | "index": 1, 11 | "subnet": { 12 | "ipv4": "192.168.16.1/24", 13 | "ipv6": "fd16::1/64" 14 | } 15 | }, 16 | "tunnel-subnet": { 17 | "ipv4": "192.168.18.0/24", 18 | "ipv6": "fd18::/64" 19 | }, 20 | "worker-addresses": [ 21 | "192.168.16.2", 22 | "192.168.16.3" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /examples/lb/main/lb.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | 12 | "github.com/intel-go/nff-go/examples/lb" 13 | ) 14 | 15 | func main() { 16 | cores := flag.String("cores", "", "Specify CPU cores to use.") 17 | configFile := flag.String("config", "config.json", "Specify config file name.") 18 | noscheduler := flag.Bool("no-scheduler", false, "Disable scheduler.") 19 | dpdkLogLevel := flag.String("dpdk", "--log-level=0", "Passes an arbitrary argument to dpdk EAL.") 20 | flag.Parse() 21 | 22 | // Read config 23 | flow.CheckFatal(lb.ReadConfig(*configFile)) 24 | 25 | nffgoconfig := flow.Config{ 26 | CPUList: *cores, 27 | DPDKArgs: []string{*dpdkLogLevel}, 28 | DisableScheduler: *noscheduler, 29 | } 30 | 31 | flow.CheckFatal(flow.SystemInit(&nffgoconfig)) 32 | lb.InitFlows() 33 | flow.CheckFatal(flow.SystemStart()) 34 | } 35 | -------------------------------------------------------------------------------- /examples/lb/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package lb 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | "github.com/intel-go/nff-go/types" 13 | ) 14 | 15 | func arpHandler(pkt *packet.Packet, ctx flow.UserContext) bool { 16 | pkt.ParseL3() 17 | protocol := pkt.Ether.EtherType 18 | 19 | if protocol == types.SwapARPNumber { 20 | err := LBConfig.TunnelPort.neighCache.HandleIPv4ARPPacket(pkt) 21 | if err != nil { 22 | fmt.Println(err) 23 | } 24 | return false 25 | } 26 | return true 27 | } 28 | -------------------------------------------------------------------------------- /examples/nffPktgen/.gitignore: -------------------------------------------------------------------------------- 1 | *.pcap 2 | -------------------------------------------------------------------------------- /examples/nffPktgen/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | IMAGENAME = nff-pktgen 7 | SUBDIRS = testing gtp-u 8 | 9 | include $(PATH_TO_MK)/intermediate.mk 10 | -------------------------------------------------------------------------------- /examples/nffPktgen/gtp-u/.gitignore: -------------------------------------------------------------------------------- 1 | trafficgen 2 | -------------------------------------------------------------------------------- /examples/nffPktgen/gtp-u/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY trafficgen . 12 | -------------------------------------------------------------------------------- /examples/nffPktgen/gtp-u/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = gtp-u-pktgen 7 | EXECUTABLES = trafficgen 8 | 9 | include $(PATH_TO_MK)/leaf.mk 10 | -------------------------------------------------------------------------------- /examples/nffPktgen/gtp-u/gen-ip4gtp-u.json: -------------------------------------------------------------------------------- 1 | { 2 | "s1u-port": { 3 | "index": 0, 4 | "dst-mac": "52:54:00:90:D4:39", 5 | "speed": 100000, 6 | "traffic-config": { 7 | "ether": { 8 | "ipv4": { 9 | "saddr": { 10 | "range": { 11 | "min": "16.0.0.1", 12 | "max": "16.7.161.32" 13 | } 14 | }, 15 | "daddr": "13.7.1.110", 16 | "udp": { 17 | "sport": 1234, 18 | "dport": 5678, 19 | "randbytes": { 20 | "size": 128, 21 | "deviation": 0 22 | } 23 | } 24 | } 25 | } 26 | }, 27 | "gtp-u-config": { 28 | "ipv4": { 29 | "saddr": { 30 | "range": { 31 | "min": "11.7.1.101", 32 | "max": "11.7.1.180" 33 | } 34 | }, 35 | "daddr": "11.7.1.93" 36 | }, 37 | "start-teid": 4026531840, 38 | "max-teids": 500000 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/nffPktgen/gtp-u/ip4gtp-u-sarp.json: -------------------------------------------------------------------------------- 1 | { 2 | "s1u-port": { 3 | "index": 0, 4 | "dst-mac": "52:54:00:90:D4:39", 5 | "speed": 100000, 6 | "traffic-config": { 7 | "ether": { 8 | "ipv4": { 9 | "saddr": { 10 | "range": { 11 | "min": "16.0.0.1", 12 | "max": "16.7.161.32" 13 | } 14 | }, 15 | "daddr": "13.7.1.110", 16 | "udp": { 17 | "sport": 1234, 18 | "dport": 5678, 19 | "randbytes": { 20 | "size": 128, 21 | "deviation": 0 22 | } 23 | } 24 | } 25 | } 26 | }, 27 | "gtp-u-config": { 28 | "ipv4": { 29 | "saddr": { 30 | "range": { 31 | "min": "11.7.1.101", 32 | "max": "11.7.1.180" 33 | } 34 | }, 35 | "daddr": "11.7.1.93" 36 | }, 37 | "start-teid": 4026531840, 38 | "max-teids": 500000 39 | } 40 | }, 41 | "sgi-port": { 42 | "index": 1, 43 | "dst-mac": "52:54:00:B9:32:8B", 44 | "speed": 100000, 45 | "traffic-config": { 46 | "ether": { 47 | "ipv4": { 48 | "saddr": "13.7.1.110", 49 | "daddr": { 50 | "range": { 51 | "min": "16.0.0.1", 52 | "max": "16.7.161.32" 53 | } 54 | }, 55 | "udp": { 56 | "sport": 5678, 57 | "dport": 1234, 58 | "randbytes": { 59 | "size": 128, 60 | "deviation": 0 61 | } 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/nffPktgen/gtp-u/ip4gtp-u.json: -------------------------------------------------------------------------------- 1 | { 2 | "s1u-port": { 3 | "index": 0, 4 | "speed": 100000, 5 | "traffic-config": { 6 | "ether": { 7 | "ipv4": { 8 | "saddr": { 9 | "range": { 10 | "min": "16.0.0.1", 11 | "max": "16.7.161.32" 12 | } 13 | }, 14 | "daddr": "13.7.1.110", 15 | "udp": { 16 | "sport": 1234, 17 | "dport": 5678, 18 | "randbytes": { 19 | "size": 128, 20 | "deviation": 0 21 | } 22 | } 23 | } 24 | } 25 | }, 26 | "gtp-u-config": { 27 | "ipv4": { 28 | "saddr": { 29 | "range": { 30 | "min": "11.7.1.101", 31 | "max": "11.7.1.180" 32 | } 33 | }, 34 | "daddr": "11.7.1.93" 35 | }, 36 | "start-teid": 4026531840, 37 | "max-teids": 500000 38 | } 39 | }, 40 | "sgi-port": { 41 | "index": 1, 42 | "speed": 100000, 43 | "traffic-config": { 44 | "ether": { 45 | "ipv4": { 46 | "saddr": "13.7.1.110", 47 | "daddr": { 48 | "range": { 49 | "min": "16.0.0.1", 50 | "max": "16.7.161.32" 51 | } 52 | }, 53 | "udp": { 54 | "sport": 5678, 55 | "dport": 1234, 56 | "randbytes": { 57 | "size": 128, 58 | "deviation": 0 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "dut-sgi-ipv4": "13.7.1.93" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /examples/nffPktgen/gtp-u/rec-ip4gtp-u.json: -------------------------------------------------------------------------------- 1 | { 2 | "sgi-port": { 3 | "index": 1, 4 | "dst-mac": "52:54:00:B9:32:8B", 5 | "speed": 100000, 6 | "traffic-config": { 7 | "ether": { 8 | "ipv4": { 9 | "saddr": "13.7.1.110", 10 | "daddr": { 11 | "range": { 12 | "min": "16.0.0.1", 13 | "max": "16.7.161.32" 14 | } 15 | }, 16 | "udp": { 17 | "sport": 5678, 18 | "dport": 1234, 19 | "randbytes": { 20 | "size": 128, 21 | "deviation": 0 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/.gitignore: -------------------------------------------------------------------------------- 1 | sendGetBack 2 | perfTest 3 | dump 4 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY sendGetBack . 12 | COPY perfTest . 13 | COPY dump . 14 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = nff-pktgen 7 | EXECUTABLES = sendGetBack perfTest dump 8 | 9 | include $(PATH_TO_MK)/leaf.mk 10 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/README.md: -------------------------------------------------------------------------------- 1 | # Packet generation, sending and receiving 2 | 3 | ## What it is 4 | Parses config files, generates output and sends to file or port and counts them. Receives packets back and counts. 5 | 6 | ### Command-line options: 7 | * --number sets the number of packets to get back and stop, default value is 10000000 8 | * --speed sets the speed of generator 9 | * --cycle sets cycle execution to generate infinite number of packets 10 | * --outConfig specifies config per port portNum or file: 'path', 'path3': 'path2'. For example: 1: 'ip4.json', 'mix.pcap': 'mix.json' 11 | * --inConfig specifies input ports and files: 'path', 'portNum2', 'path2'. For example: 1, 'ip4.pcap', 0, 'mix.pcap' 12 | 13 | ### Example of usage: 14 | To run generation from "mix.json" config to port number 1 and from "../../ip4tcp.json" to file "ip4tcp.pcap" and receive packets from 15 | port 0 and file "../../ip4tcp.pcap" run: 16 | ``` 17 | ./sendGetBack --outConfig "1: 'mix.json', ip4tcp.pcap: '../../ip4tcp.json'" --inConfig "0, '../../ip4tcp.json'" 18 | ``` -------------------------------------------------------------------------------- /examples/nffPktgen/testing/arp.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "arp": { 4 | "opcode": 1, 5 | "gratuitous" : true, 6 | "sha": "99:25:96:FF:FE:12", 7 | "spa": "1.1.1.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/arpVlan.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "vlan-tci": 200, 4 | "arp": { 5 | "opcode": 1, 6 | "gratuitous" : true, 7 | "sha": "99:25:96:FF:FE:12", 8 | "spa": "1.1.1.2" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 3 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "ipv4": { 13 | "saddr": { 14 | "range": { 15 | "min": "1.1.127.1", 16 | "max": "255.0.0.0" 17 | } 18 | }, 19 | "daddr": "1.1.127.0", 20 | "icmp": { 21 | "type": 10, 22 | "code": 1, 23 | "seq": "increasing", 24 | "pdist": [ 25 | { 26 | "probability": 0.5, 27 | "randbytes": { 28 | "size": 50, 29 | "deviation": 10 30 | } 31 | }, 32 | { 33 | "probability": 0.5, 34 | "raw": { 35 | "data": "sfsfsfs" 36 | } 37 | } 38 | ] 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/dump.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "github.com/intel-go/nff-go/examples/nffPktgen/generator" 11 | "github.com/intel-go/nff-go/flow" 12 | "github.com/intel-go/nff-go/packet" 13 | "os" 14 | ) 15 | 16 | func main() { 17 | name := flag.String("m", "", "filename") 18 | flag.Parse() 19 | // Init NFF-GO system at 16 available cores 20 | config := flow.Config{ 21 | CPUList: "0-43", 22 | DisableScheduler: true, 23 | } 24 | flow.CheckFatal(flow.SystemInit(&config)) 25 | 26 | configuration, err := generator.ReadConfig(*name) 27 | flow.CheckFatal(err) 28 | context, err1 := generator.GetContext(configuration) 29 | flow.CheckFatal(err1) 30 | 31 | outFlow, _, _ := flow.SetFastGenerator(generator.Generate, 100, context) 32 | flow.SetHandler(outFlow, handleRecv, nil) 33 | flow.SetStopper(outFlow) 34 | flow.CheckFatal(flow.SystemStart()) 35 | } 36 | 37 | var got int 38 | 39 | func handleRecv(currentPacket *packet.Packet, context flow.UserContext) { 40 | got++ 41 | fmt.Printf("Raw bytes=%x\n", currentPacket.GetRawPacketBytes()) 42 | if got > 25 { 43 | os.Exit(0) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ether.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 10 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "randbytes": { 13 | "size": 500, 14 | "deviation": 300 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip4.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "max": "00:FF:96:FF:FE:12", 7 | "inc": 10 8 | } 9 | }, 10 | "daddr": "00:00:96:FF:00:00", 11 | "ipv4": { 12 | "saddr": "1.1.127.1", 13 | "daddr": { 14 | "range": { 15 | "min": "1.1.1.1", 16 | "max": "1.1.3.3" 17 | } 18 | }, 19 | 20 | "raw": { 21 | "data": "023a0232ff9340x0340123" 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip4icmp.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 3 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "ipv4": { 13 | "saddr": "1.1.127.1", 14 | "daddr": "1.1.127.0", 15 | "icmp": { 16 | "type": 10, 17 | "code": 1, 18 | "seq": "increasing", 19 | "pdist": [ 20 | { 21 | "probability": 0.33, 22 | "randbytes": { 23 | "size": 50, 24 | "deviation": 10 25 | } 26 | }, 27 | { 28 | "probability": 0.33, 29 | "raw": { 30 | "data": "sfsfsfs" 31 | } 32 | }, 33 | { 34 | "probability": 0.34, 35 | "raw": { 36 | "data": "0000000000000000000000000000000000" 37 | } 38 | } 39 | ] 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip4tcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 3 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "ipv4": { 13 | "saddr": "1.1.127.1", 14 | "daddr": "1.1.127.0", 15 | "tcp": { 16 | "sport": { 17 | "range": { 18 | "min": 1, 19 | "max": 8080, 20 | "inc": 100 21 | } 22 | }, 23 | "dport": 2000, 24 | "seq": "increasing", 25 | "flags": ["ack", "fin", "syn"], 26 | "pdist": [ 27 | { 28 | "probability": 0.5, 29 | "randbytes": { 30 | "size": 50, 31 | "deviation": 10 32 | } 33 | }, 34 | { 35 | "probability": 0.5, 36 | "raw": { 37 | "data": "sfsfsfs" 38 | } 39 | } 40 | ] 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip4tcpVlan.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 3 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "vlan-tci": 123, 13 | "ipv4": { 14 | "saddr": "1.1.127.1", 15 | "daddr": "1.1.127.0", 16 | "tcp": { 17 | "sport": { 18 | "range": { 19 | "min": 1, 20 | "max": 8080, 21 | "inc": 100 22 | } 23 | }, 24 | "dport": 2000, 25 | "seq": "increasing", 26 | "flags": ["ack", "fin", "syn"], 27 | "pdist": [ 28 | { 29 | "probability": 0.5, 30 | "randbytes": { 31 | "size": 50, 32 | "deviation": 10 33 | } 34 | }, 35 | { 36 | "probability": 0.5, 37 | "raw": { 38 | "data": "sfsfsfs" 39 | } 40 | } 41 | ] 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip4udp.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 3 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "ipv4": { 13 | "saddr": "1.1.127.1", 14 | "daddr": "1.1.127.0", 15 | "udp": { 16 | "sport": { 17 | "range": { 18 | "min": 1, 19 | "max": 8080, 20 | "inc": 100 21 | } 22 | }, 23 | "dport": 2000, 24 | "pdist": [ 25 | { 26 | "probability": 0.5, 27 | "randbytes": { 28 | "size": 50, 29 | "deviation": 10 30 | } 31 | }, 32 | { 33 | "probability": 0.5, 34 | "raw": { 35 | "data": "sfsfsfs" 36 | } 37 | } 38 | ] 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip4udpVlan.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 3 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "vlan-tci": 123, 13 | "ipv4": { 14 | "saddr": "1.1.127.1", 15 | "daddr": "1.1.127.0", 16 | "udp": { 17 | "sport": { 18 | "range": { 19 | "min": 1, 20 | "max": 8080, 21 | "inc": 100 22 | } 23 | }, 24 | "dport": 2000, 25 | "pdist": [ 26 | { 27 | "probability": 0.5, 28 | "randbytes": { 29 | "size": 50, 30 | "deviation": 10 31 | } 32 | }, 33 | { 34 | "probability": 0.5, 35 | "raw": { 36 | "data": "sfsfsfs" 37 | } 38 | } 39 | ] 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip6.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "max": "00:FF:96:FF:FE:12", 7 | "inc": 10 8 | } 9 | }, 10 | "daddr": "00:00:96:FF:00:00", 11 | "ipv6": { 12 | "saddr": "2001:db8:a0b:12f0::", 13 | "pdist": [ 14 | { 15 | "probability": 1, 16 | "randbytes": { 17 | "size": 70 18 | } 19 | } 20 | ] 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip6icmp.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 3 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "ipv6": { 13 | "icmp": { 14 | "type": 10, 15 | "code": 1, 16 | "seq": "increasing", 17 | "pdist": [ 18 | { 19 | "probability": 0.5, 20 | "randbytes": { 21 | "size": 50, 22 | "deviation": 10 23 | } 24 | }, 25 | { 26 | "probability": 0.5, 27 | "raw": { 28 | "data": "0000000000000000000000000000000000" 29 | } 30 | } 31 | ] 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip6tcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 3 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "ipv6": { 13 | "saddr": "2001:db8:a0b:12f0::1", 14 | "daddr": "2001:db8:a0b:12f0::1", 15 | "tcp": { 16 | "sport": { 17 | "range": { 18 | "min": 1, 19 | "max": 8080, 20 | "inc": 100 21 | } 22 | }, 23 | "dport": 2000, 24 | "seq": "increasing", 25 | "flags": ["ack", "fin", "syn"], 26 | "pdist": [ 27 | { 28 | "probability": 0.7, 29 | "randbytes": { 30 | "size": 50, 31 | "deviation": 10 32 | } 33 | }, 34 | { 35 | "probability": 0.3, 36 | "raw": { 37 | "data": "sfsfsfs" 38 | } 39 | } 40 | ] 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/ip6udp.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "start": "00:30:00:FF:FE:12", 7 | "max": "00:FF:96:FF:FE:12", 8 | "inc": 3 9 | } 10 | }, 11 | "daddr": "00:FF:96:FF:FE:12", 12 | "ipv6": { 13 | "saddr": "2001:db8:a0b:12f0::1", 14 | "daddr": "2001:db8:a0b:12f0::1", 15 | "udp": { 16 | "sport": { 17 | "range": { 18 | "min": 1, 19 | "max": 8080, 20 | "inc": 100 21 | } 22 | }, 23 | "dport": 2000, 24 | "randbytes": { 25 | "size": 50, 26 | "deviation": 10 27 | } 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/pcap.json: -------------------------------------------------------------------------------- 1 | { 2 | "pcap": { 3 | "path": "./test.pcap", 4 | "inmemory": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./sendGetBack -number 100000 -outConfig "'ether.pcap': 'ether.json'" 4 | ./sendGetBack -number 10000 -outConfig "'ip4.pcap':'ip4.json'" 5 | ./sendGetBack -number 1000 -outConfig "'ip6.pcap':'ip6.json'" 6 | ./sendGetBack -number 100000 -outConfig "'ip4tcp.pcap':'ip4tcp.json'" 7 | ./sendGetBack -number 100000 -outConfig "'ip4tcpVlan.pcap':'ip4tcpVlan.json'" 8 | ./sendGetBack -number 1000000 -outConfig "'ip6tcp.pcap':'ip6tcp.json'" 9 | ./sendGetBack -number 10000 -outConfig "'ip4udp.pcap':'ip4udp.json'" 10 | ./sendGetBack -number 10000 -outConfig "'ip4udpVlan.pcap':'ip4udpVlan.json'" 11 | ./sendGetBack -number 1000 -outConfig "'ip6udp.pcap':'ip6udp.json'" 12 | ./sendGetBack -number 1000000 -outConfig "'ip4icmp.pcap':'ip4icmp.json'" 13 | ./sendGetBack -number 100000 -outConfig "'ip6icmp.pcap':'ip6icmp.json'" 14 | ./sendGetBack -number 1000 -outConfig "'arp.pcap':'arp.json'" 15 | ./sendGetBack -number 100 -outConfig "'vlanTag.pcap':'vlanTag.json'" 16 | ./sendGetBack -number 100 -outConfig "'arpVlan.pcap':'arpVlan.json'" 17 | ./sendGetBack -number 100 -outConfig "'config.pcap': 'config.json'" 18 | ./sendGetBack -number 100 -outConfig "'mix.pcap': 'mix.json'" 19 | ./sendGetBack -number 100 -outConfig "'pcap.pcap': 'pcap.json'" 20 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/test.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aregm/nff-go/3fcc11eab4030598949f7e34be99ed8f70221e08/examples/nffPktgen/testing/test.pcap -------------------------------------------------------------------------------- /examples/nffPktgen/testing/testnat.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": "00:25:96:FF:FE:12", 4 | "daddr": "00:FF:96:FF:FE:12", 5 | "ipv4": { 6 | "saddr": { 7 | "range": { 8 | "min": "192.16.0.0", 9 | "max": "192.16.0.255" 10 | } 11 | }, 12 | "daddr": { 13 | "range": { 14 | "min": "172.16.0.0", 15 | "max": "172.16.0.10" 16 | } 17 | }, 18 | "udp": { 19 | "sport": { 20 | "range": { 21 | "min": 1120, 22 | "max": 1152 23 | } 24 | }, 25 | "dport": 1020, 26 | "raw": { 27 | "data": "123456789012345678" 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/nffPktgen/testing/vlanTag.json: -------------------------------------------------------------------------------- 1 | { 2 | "ether": { 3 | "saddr": { 4 | "range": { 5 | "min": "00:25:96:FF:FE:12", 6 | "max": "00:FF:96:FF:FE:12", 7 | "inc": 10 8 | } 9 | }, 10 | "daddr": "00:00:96:FF:00:00", 11 | "vlan-tci": 123, 12 | "ipv6": { 13 | "saddr": "2001:db8:a0b:12f0::", 14 | "pdist": [ 15 | { 16 | "probability": 1, 17 | "randbytes": { 18 | "size": 70 19 | } 20 | } 21 | ] 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/pingReplay.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "github.com/intel-go/nff-go/flow" 6 | "github.com/intel-go/nff-go/types" 7 | ) 8 | 9 | func main() { 10 | inport := flag.Uint("inport", 0, "port for receiver") 11 | flag.Parse() 12 | 13 | flow.CheckFatal(flow.SystemInit(nil)) 14 | 15 | inputFlow, err := flow.SetReceiver(uint16(*inport)) 16 | flow.CheckFatal(err) 17 | 18 | flow.CheckFatal(flow.SetIPForPort(uint16(*inport), types.IPv4Address(20)<<24|types.IPv4Address(20)<<16|types.IPv4Address(20)<<8|types.IPv4Address(20))) 19 | 20 | flow.CheckFatal(flow.DealARPICMP(inputFlow)) 21 | flow.CheckFatal(flow.SetStopper(inputFlow)) 22 | 23 | flow.CheckFatal(flow.SystemStart()) 24 | } 25 | -------------------------------------------------------------------------------- /examples/sendFixedPktsNumber.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "os" 10 | "sync/atomic" 11 | 12 | "github.com/intel-go/nff-go/flow" 13 | "github.com/intel-go/nff-go/packet" 14 | ) 15 | 16 | var totalPackets int64 17 | var count int64 18 | var payloadSize uint 19 | 20 | func main() { 21 | flag.Int64Var(&totalPackets, "totalPackets", 1234, "Number of packets to send") 22 | packetSize := flag.Uint("packetSize", 128, "Size of generated packet") 23 | outport := flag.Uint("outport", 0, "port for sender") 24 | flag.Parse() 25 | 26 | // Total packet size is 14+20+20+payload_size+4(crc) 27 | hdrsSize := uint(14 + 20 + 20 + 4) 28 | payloadSize = *packetSize - hdrsSize 29 | 30 | // Initialize NFF-GO library at 16 cores by default 31 | config := flow.Config{ 32 | CPUList: "0-15", 33 | } 34 | flow.CheckFatal(flow.SystemInit(&config)) 35 | 36 | // With generator all packets are sent. 37 | f1 := flow.SetGenerator(generatePacket, nil) 38 | 39 | // With fast generator sent only multiple of burst-size. 40 | // f1 := flow.SetFastGenerator(generatePacket, 100, nil) 41 | 42 | // Send all generated packets to the output 43 | flow.CheckFatal(flow.SetSender(f1, uint16(*outport))) 44 | 45 | flow.CheckFatal(flow.SystemStart()) 46 | } 47 | 48 | func generatePacket(pkt *packet.Packet, context flow.UserContext) { 49 | sent := atomic.LoadInt64(&count) 50 | if packet.InitEmptyIPv4TCPPacket(pkt, payloadSize) == false { 51 | panic("Failed to init empty packet") 52 | } 53 | pkt.Ether.DAddr = [6]uint8{0x00, 0x11, 0x22, 0x33, 0x44, 0x55} 54 | if sent >= totalPackets { 55 | println("Sent ", sent, "number of packets") 56 | os.Exit(0) 57 | } 58 | atomic.AddInt64(&count, 1) 59 | } 60 | -------------------------------------------------------------------------------- /examples/timer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "time" 11 | 12 | "github.com/intel-go/nff-go/flow" 13 | "github.com/intel-go/nff-go/packet" 14 | ) 15 | 16 | var t *flow.Timer 17 | var check *bool 18 | var inport *uint 19 | var duration *time.Duration 20 | 21 | func main() { 22 | inport = flag.Uint("inport", 0, "port for receiver") 23 | duration = flag.Duration("duration", 2000*time.Millisecond, "seconds to react") 24 | flag.Parse() 25 | 26 | flow.CheckFatal(flow.SystemInit(nil)) 27 | 28 | firstFlow, err := flow.SetReceiver(uint16(*inport)) 29 | flow.CheckFatal(err) 30 | flow.CheckFatal(flow.SetHandler(firstFlow, handler, nil)) 31 | flow.CheckFatal(flow.SetStopper(firstFlow)) 32 | 33 | t = flow.AddTimer(*duration, react) 34 | flow.CheckFatal(flow.SystemStart()) 35 | } 36 | 37 | func handler(currentPacket *packet.Packet, context flow.UserContext) { 38 | if check == nil { 39 | check = t.AddVariant(nil) 40 | } 41 | *check = true 42 | } 43 | 44 | func react(context flow.UserContext) { 45 | fmt.Println(*duration, "after last packet was arrived") 46 | 47 | answerPacket, _ := packet.NewPacket() 48 | packet.InitEmptyIPv4Packet(answerPacket, 64) 49 | answerPacket.SendPacket(uint16(*inport)) 50 | 51 | check = nil 52 | } 53 | -------------------------------------------------------------------------------- /examples/tutorial/.gitignore: -------------------------------------------------------------------------------- 1 | genscripts 2 | step01 3 | step02 4 | step03 5 | step04 6 | step05 7 | step06 8 | step07 9 | step08 10 | step09 11 | step10 12 | step11 13 | nat.json 14 | -------------------------------------------------------------------------------- /examples/tutorial/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | 12 | COPY step01 . 13 | COPY step02 . 14 | COPY step03 . 15 | COPY step04 . 16 | COPY step05 . 17 | COPY step06 . 18 | COPY step07 . 19 | COPY step08 . 20 | COPY step09 . 21 | COPY step10 . 22 | COPY step11 . 23 | COPY rules1.conf . 24 | COPY rules2.conf . 25 | -------------------------------------------------------------------------------- /examples/tutorial/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | IMAGENAME = steps 7 | EXECUTABLES = genscripts step01 step02 step03 step04 step05 step06 step07 step08 step09 step10 step11 8 | COMMON_FILES = common.go 9 | 10 | include $(PATH_TO_MK)/leaf.mk 11 | -------------------------------------------------------------------------------- /examples/tutorial/NFF-Go tutorial.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aregm/nff-go/3fcc11eab4030598949f7e34be99ed8f70221e08/examples/tutorial/NFF-Go tutorial.pdf -------------------------------------------------------------------------------- /examples/tutorial/common.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "log" 7 | "net" 8 | "os" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | "github.com/intel-go/nff-go/types" 13 | ) 14 | 15 | var config map[string][]string 16 | var dstMac0 [types.EtherAddrLen]uint8 17 | var srcMac0 [types.EtherAddrLen]uint8 18 | var dstMac1 [types.EtherAddrLen]uint8 19 | var srcMac1 [types.EtherAddrLen]uint8 20 | var modifyPacket = []func(pkt *packet.Packet, ctx flow.UserContext){modifyPacket0, modifyPacket1} 21 | var direct = "direct" 22 | 23 | const flowN = 3 24 | 25 | // readConfig function reads and parses config file 26 | func readConfig(fileName string) error { 27 | file, err := os.Open(fileName) 28 | if err != nil { 29 | return err 30 | } 31 | decoder := json.NewDecoder(file) 32 | 33 | err = decoder.Decode(&config) 34 | if err != nil { 35 | return err 36 | } 37 | 38 | return nil 39 | } 40 | 41 | func printMAC(prompt string, mac [types.EtherAddrLen]uint8) { 42 | log.Printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", prompt, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) 43 | } 44 | 45 | func initCommonState() { 46 | // Parse arguments 47 | configFile := flag.String("config", "config.json", "Specify config file name") 48 | target := flag.String("target", "direct", "Target host name from config file or \"direct\" reserved word") 49 | flag.Parse() 50 | 51 | // Get source MAC addresses for port 0 and 1 52 | srcMac0 = flow.GetPortMACAddress(0) 53 | printMAC("Source MAC 0", srcMac0) 54 | srcMac1 = flow.GetPortMACAddress(1) 55 | printMAC("Source MAC 1", srcMac1) 56 | 57 | // Read config 58 | err := readConfig(*configFile) 59 | if err != nil { 60 | log.Fatal(err) 61 | } 62 | 63 | // Get destination MAC addresses for port 0 and 1 64 | if hw, err := net.ParseMAC(config[*target][0]); err == nil { 65 | copy(dstMac0[:], hw) 66 | } else { 67 | log.Fatal(err) 68 | } 69 | printMAC("Destination MAC 0", dstMac0) 70 | if hw, err := net.ParseMAC(config[*target][1]); err == nil { 71 | copy(dstMac1[:], hw) 72 | } else { 73 | log.Fatal(err) 74 | } 75 | printMAC("Destination MAC 1", dstMac1) 76 | } 77 | 78 | func modifyPacket0(pkt *packet.Packet, ctx flow.UserContext) { 79 | pkt.Ether.DAddr = dstMac0 80 | pkt.Ether.SAddr = srcMac0 81 | } 82 | 83 | func modifyPacket1(pkt *packet.Packet, ctx flow.UserContext) { 84 | pkt.Ether.DAddr = dstMac1 85 | pkt.Ether.SAddr = srcMac1 86 | } 87 | -------------------------------------------------------------------------------- /examples/tutorial/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "direct": [ 3 | "11:22:33:44:55:66", 4 | "77:88:99:aa:bb:cc" 5 | ], 6 | "dcomp01": [ 7 | "3c:fd:fe:9d:6a:c2", 8 | "3c:fd:fe:9d:6a:c3" 9 | ], 10 | "dcomp02": [ 11 | "3c:fd:fe:9d:67:ea", 12 | "3c:fd:fe:9d:67:eb" 13 | ], 14 | "dcomp03": [ 15 | "3c:fd:fe:9d:6a:ba", 16 | "3c:fd:fe:9d:6a:bb" 17 | ], 18 | "dcomp10": [ 19 | "3c:fd:fe:9d:69:2a", 20 | "3c:fd:fe:9d:69:2b" 21 | ], 22 | "dcomp11": [ 23 | "3c:fd:fe:9d:63:1a", 24 | "3c:fd:fe:9d:63:1b" 25 | ], 26 | "dcomp12": [ 27 | "3c:fd:fe:9d:6a:fa", 28 | "3c:fd:fe:9d:6a:fb" 29 | ], 30 | "dbdw04": [ 31 | "90:e2:ba:af:c5:70", 32 | "90:e2:ba:af:c5:71" 33 | ], 34 | "dbdw05": [ 35 | "90:e2:ba:af:b0:80", 36 | "90:e2:ba:af:b0:81" 37 | ], 38 | "dbdw06": [ 39 | "90:e2:ba:af:d7:f8", 40 | "90:e2:ba:af:d7:f9" 41 | ], 42 | "dbdw07": [ 43 | "90:e2:ba:c6:7a:74", 44 | "90:e2:ba:c6:7a:75" 45 | ], 46 | "dbdw08": [ 47 | "90:e2:ba:c6:7e:00", 48 | "90:e2:ba:c6:7e:01" 49 | ], 50 | "dbdw09": [ 51 | "90:e2:ba:af:d7:f0", 52 | "90:e2:ba:af:d7:f1" 53 | ], 54 | "dbdw10": [ 55 | "90:e2:ba:b1:e1:f4", 56 | "90:e2:ba:b1:e1:f5" 57 | ], 58 | "dbdw11": [ 59 | "90:e2:ba:b1:e2:00", 60 | "90:e2:ba:b1:e2:01" 61 | ], 62 | "dbdw12": [ 63 | "90:e2:ba:b1:dd:c8", 64 | "90:e2:ba:b1:dd:c9" 65 | ], 66 | "dbdw13": [ 67 | "90:e2:ba:b1:e1:d4", 68 | "90:e2:ba:b1:e1:d5" 69 | ], 70 | "dbdw14": [ 71 | "90:e2:ba:b1:e1:d8", 72 | "90:e2:ba:b1:e1:d9" 73 | ], 74 | "dbdw15": [ 75 | "90:e2:ba:b1:dd:bc", 76 | "90:e2:ba:b1:dd:bd" 77 | ], 78 | "dbdw16": [ 79 | "90:e2:ba:d3:70:dc", 80 | "90:e2:ba:d3:70:dd" 81 | ], 82 | "dbdw17": [ 83 | "90:e2:ba:b1:07:e8", 84 | "90:e2:ba:b1:07:e9" 85 | ] 86 | } 87 | -------------------------------------------------------------------------------- /examples/tutorial/rules1.conf: -------------------------------------------------------------------------------- 1 | # This file is used in "Forwarding.go" example. It divides packets to four flows and drop some of them 2 | 3 | # Source address, Destination address, L4 protocol ID, Source port, Destination port, Output flow 4 | 111.2.0.0/31 ANY ANY ANY ANY Accept 5 | 111.2.0.2/32 ANY ANY ANY ANY Reject 6 | ANY ANY ANY ANY ANY Accept 7 | -------------------------------------------------------------------------------- /examples/tutorial/rules2.conf: -------------------------------------------------------------------------------- 1 | # This file is used in "Forwarding.go" example. It divides packets to four flows and drop some of them 2 | 3 | # Source address, Destination address, L4 protocol ID, Source port, Destination port, Output flow 4 | 111.2.0.0/31 ANY ANY ANY ANY 1 5 | 111.2.0.2/32 ANY ANY ANY ANY 0 6 | ANY ANY ANY ANY ANY 2 7 | -------------------------------------------------------------------------------- /examples/tutorial/runpktgen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd ../../dpdk 4 | sudo ./pktgen -c 0xff -n 4 -- -P -m "[1:2].0, [3:4].1" -T 5 | rc=$?; if [[ $rc == 0 ]]; then reset; fi 6 | -------------------------------------------------------------------------------- /examples/tutorial/step01.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/intel-go/nff-go/flow" 4 | 5 | func main() { 6 | // Init NFF-GO system 7 | flow.CheckFatal(flow.SystemInit(nil)) 8 | 9 | initCommonState() 10 | 11 | flow.CheckFatal(flow.SystemStart()) 12 | } 13 | -------------------------------------------------------------------------------- /examples/tutorial/step02.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/intel-go/nff-go/flow" 4 | 5 | func main() { 6 | flow.CheckFatal(flow.SystemInit(nil)) 7 | 8 | initCommonState() 9 | 10 | firstFlow, err := flow.SetReceiver(0) 11 | flow.CheckFatal(err) 12 | flow.CheckFatal(flow.SetHandler(firstFlow, modifyPacket[0], nil)) 13 | flow.CheckFatal(flow.SetSender(firstFlow, 0)) 14 | 15 | flow.CheckFatal(flow.SystemStart()) 16 | } 17 | -------------------------------------------------------------------------------- /examples/tutorial/step03.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/intel-go/nff-go/flow" 4 | 5 | func main() { 6 | flow.CheckFatal(flow.SystemInit(nil)) 7 | 8 | initCommonState() 9 | 10 | firstFlow, err := flow.SetReceiver(0) 11 | flow.CheckFatal(err) 12 | secondFlow, err := flow.SetPartitioner(firstFlow, 300, 300) 13 | flow.CheckFatal(err) 14 | flow.CheckFatal(flow.SetHandler(firstFlow, modifyPacket[0], nil)) 15 | flow.CheckFatal(flow.SetHandler(secondFlow, modifyPacket[1], nil)) 16 | flow.CheckFatal(flow.SetSender(firstFlow, 0)) 17 | flow.CheckFatal(flow.SetSender(secondFlow, 1)) 18 | 19 | flow.CheckFatal(flow.SystemStart()) 20 | } 21 | -------------------------------------------------------------------------------- /examples/tutorial/step04.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/intel-go/nff-go/flow" 4 | import "github.com/intel-go/nff-go/packet" 5 | 6 | func main() { 7 | flow.CheckFatal(flow.SystemInit(nil)) 8 | 9 | initCommonState() 10 | 11 | firstFlow, err := flow.SetReceiver(0) 12 | flow.CheckFatal(err) 13 | secondFlow, err := flow.SetSeparator(firstFlow, mySeparator, nil) 14 | flow.CheckFatal(err) 15 | flow.CheckFatal(flow.SetHandler(firstFlow, modifyPacket[0], nil)) 16 | flow.CheckFatal(flow.SetHandler(secondFlow, modifyPacket[1], nil)) 17 | flow.CheckFatal(flow.SetSender(firstFlow, 0)) 18 | flow.CheckFatal(flow.SetSender(secondFlow, 1)) 19 | 20 | flow.CheckFatal(flow.SystemStart()) 21 | } 22 | 23 | func mySeparator(cur *packet.Packet, ctx flow.UserContext) bool { 24 | cur.ParseL3() 25 | if cur.GetIPv4() != nil { 26 | cur.ParseL4ForIPv4() 27 | if cur.GetTCPForIPv4() != nil && packet.SwapBytesUint16(cur.GetTCPForIPv4().DstPort) == 53 { 28 | return false 29 | } 30 | } 31 | return true 32 | } 33 | -------------------------------------------------------------------------------- /examples/tutorial/step05.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/intel-go/nff-go/flow" 4 | import "github.com/intel-go/nff-go/packet" 5 | 6 | var l3Rules *packet.L3Rules 7 | 8 | func main() { 9 | var err error 10 | flow.CheckFatal(flow.SystemInit(nil)) 11 | 12 | initCommonState() 13 | 14 | l3Rules, err = packet.GetL3ACLFromTextTable("rules1.conf") 15 | flow.CheckFatal(err) 16 | 17 | firstFlow, err := flow.SetReceiver(0) 18 | flow.CheckFatal(err) 19 | secondFlow, err := flow.SetSeparator(firstFlow, mySeparator, nil) 20 | flow.CheckFatal(err) 21 | flow.CheckFatal(flow.SetHandler(firstFlow, modifyPacket[0], nil)) 22 | flow.CheckFatal(flow.SetHandler(secondFlow, modifyPacket[1], nil)) 23 | flow.CheckFatal(flow.SetSender(firstFlow, 0)) 24 | flow.CheckFatal(flow.SetSender(secondFlow, 1)) 25 | flow.CheckFatal(flow.SystemStart()) 26 | } 27 | 28 | func mySeparator(cur *packet.Packet, ctx flow.UserContext) bool { 29 | return cur.L3ACLPermit(l3Rules) 30 | } 31 | -------------------------------------------------------------------------------- /examples/tutorial/step06.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/intel-go/nff-go/flow" 4 | import "github.com/intel-go/nff-go/packet" 5 | 6 | var l3Rules *packet.L3Rules 7 | 8 | func main() { 9 | var err error 10 | flow.CheckFatal(flow.SystemInit(nil)) 11 | 12 | initCommonState() 13 | 14 | l3Rules, err = packet.GetL3ACLFromTextTable("rules1.conf") 15 | flow.CheckFatal(err) 16 | 17 | firstFlow, err := flow.SetReceiver(0) 18 | flow.CheckFatal(err) 19 | secondFlow, err := flow.SetSeparator(firstFlow, mySeparator, nil) 20 | flow.CheckFatal(err) 21 | flow.CheckFatal(flow.SetHandler(firstFlow, modifyPacket[0], nil)) 22 | flow.CheckFatal(flow.SetSender(firstFlow, 0)) 23 | flow.CheckFatal(flow.SetStopper(secondFlow)) 24 | flow.CheckFatal(flow.SystemStart()) 25 | } 26 | 27 | func mySeparator(cur *packet.Packet, ctx flow.UserContext) bool { 28 | return cur.L3ACLPermit(l3Rules) 29 | } 30 | -------------------------------------------------------------------------------- /examples/tutorial/step07.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync/atomic" 4 | import "time" 5 | import "unsafe" 6 | import "github.com/intel-go/nff-go/flow" 7 | import "github.com/intel-go/nff-go/packet" 8 | 9 | var rulesp unsafe.Pointer 10 | 11 | func main() { 12 | flow.CheckFatal(flow.SystemInit(nil)) 13 | 14 | initCommonState() 15 | 16 | l3Rules, err := packet.GetL3ACLFromTextTable("rules1.conf") 17 | flow.CheckFatal(err) 18 | rulesp = unsafe.Pointer(l3Rules) 19 | go updateSeparateRules() 20 | 21 | firstFlow, err := flow.SetReceiver(0) 22 | flow.CheckFatal(err) 23 | secondFlow, err := flow.SetSeparator(firstFlow, mySeparator, nil) 24 | flow.CheckFatal(err) 25 | flow.CheckFatal(flow.SetHandler(firstFlow, modifyPacket[0], nil)) 26 | flow.CheckFatal(flow.SetHandler(secondFlow, modifyPacket[1], nil)) 27 | flow.CheckFatal(flow.SetSender(firstFlow, 0)) 28 | flow.CheckFatal(flow.SetStopper(secondFlow)) 29 | flow.CheckFatal(flow.SystemStart()) 30 | } 31 | 32 | func mySeparator(cur *packet.Packet, ctx flow.UserContext) bool { 33 | localL3Rules := (*packet.L3Rules)(atomic.LoadPointer(&rulesp)) 34 | return cur.L3ACLPermit(localL3Rules) 35 | } 36 | 37 | func updateSeparateRules() { 38 | for { 39 | time.Sleep(time.Second * 5) 40 | locall3Rules, err := packet.GetL3ACLFromTextTable("rules1.conf") 41 | flow.CheckFatal(err) 42 | atomic.StorePointer(&rulesp, unsafe.Pointer(locall3Rules)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/tutorial/step08.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync/atomic" 4 | import "time" 5 | import "unsafe" 6 | import "github.com/intel-go/nff-go/flow" 7 | import "github.com/intel-go/nff-go/packet" 8 | 9 | var rulesp unsafe.Pointer 10 | 11 | func main() { 12 | flow.CheckFatal(flow.SystemInit(nil)) 13 | 14 | initCommonState() 15 | 16 | l3Rules, err := packet.GetL3ACLFromTextTable("rules2.conf") 17 | flow.CheckFatal(err) 18 | rulesp = unsafe.Pointer(l3Rules) 19 | go updateSeparateRules() 20 | 21 | firstFlow, err := flow.SetReceiver(0) 22 | flow.CheckFatal(err) 23 | outputFlows, err := flow.SetSplitter(firstFlow, mySplitter, flowN, nil) 24 | flow.CheckFatal(err) 25 | flow.CheckFatal(flow.SetStopper(outputFlows[0])) 26 | for i := uint16(1); i < flowN; i++ { 27 | flow.CheckFatal(flow.SetHandler(outputFlows[i], modifyPacket[i-1], nil)) 28 | flow.CheckFatal(flow.SetSender(outputFlows[i], i-1)) 29 | } 30 | flow.CheckFatal(flow.SystemStart()) 31 | } 32 | 33 | func mySplitter(cur *packet.Packet, ctx flow.UserContext) uint { 34 | localL3Rules := (*packet.L3Rules)(atomic.LoadPointer(&rulesp)) 35 | return cur.L3ACLPort(localL3Rules) 36 | } 37 | 38 | func updateSeparateRules() { 39 | for { 40 | time.Sleep(time.Second * 5) 41 | locall3Rules, err := packet.GetL3ACLFromTextTable("rules2.conf") 42 | flow.CheckFatal(err) 43 | atomic.StorePointer(&rulesp, unsafe.Pointer(locall3Rules)) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/tutorial/step09.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync/atomic" 4 | import "time" 5 | import "unsafe" 6 | import "github.com/intel-go/nff-go/types" 7 | import "github.com/intel-go/nff-go/flow" 8 | import "github.com/intel-go/nff-go/packet" 9 | 10 | var rulesp unsafe.Pointer 11 | 12 | func main() { 13 | flow.CheckFatal(flow.SystemInit(nil)) 14 | 15 | initCommonState() 16 | 17 | l3Rules, err := packet.GetL3ACLFromTextTable("rules2.conf") 18 | flow.CheckFatal(err) 19 | rulesp = unsafe.Pointer(l3Rules) 20 | go updateSeparateRules() 21 | 22 | firstFlow, err := flow.SetReceiver(0) 23 | flow.CheckFatal(err) 24 | outputFlows, err := flow.SetSplitter(firstFlow, mySplitter, flowN, nil) 25 | flow.CheckFatal(err) 26 | flow.CheckFatal(flow.SetStopper(outputFlows[0])) 27 | flow.CheckFatal(flow.SetHandler(outputFlows[1], myHandler, nil)) 28 | for i := uint16(1); i < flowN; i++ { 29 | flow.CheckFatal(flow.SetHandler(outputFlows[i], modifyPacket[i-1], nil)) 30 | flow.CheckFatal(flow.SetSender(outputFlows[i], i-1)) 31 | } 32 | flow.CheckFatal(flow.SystemStart()) 33 | } 34 | 35 | func mySplitter(cur *packet.Packet, ctx flow.UserContext) uint { 36 | localL3Rules := (*packet.L3Rules)(atomic.LoadPointer(&rulesp)) 37 | return cur.L3ACLPort(localL3Rules) 38 | } 39 | 40 | func myHandler(cur *packet.Packet, ctx flow.UserContext) { 41 | cur.EncapsulateHead(types.EtherLen, types.IPv4MinLen) 42 | cur.ParseL3() 43 | cur.GetIPv4NoCheck().SrcAddr = types.BytesToIPv4(111, 22, 3, 0) 44 | cur.GetIPv4NoCheck().DstAddr = types.BytesToIPv4(3, 22, 111, 0) 45 | cur.GetIPv4NoCheck().VersionIhl = 0x45 46 | cur.GetIPv4NoCheck().NextProtoID = 0x04 47 | } 48 | 49 | func updateSeparateRules() { 50 | for { 51 | time.Sleep(time.Second * 5) 52 | locall3Rules, err := packet.GetL3ACLFromTextTable("rules2.conf") 53 | flow.CheckFatal(err) 54 | atomic.StorePointer(&rulesp, unsafe.Pointer(locall3Rules)) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/tutorial/step10.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync/atomic" 4 | import "time" 5 | import "unsafe" 6 | import "github.com/intel-go/nff-go/types" 7 | import "github.com/intel-go/nff-go/flow" 8 | import "github.com/intel-go/nff-go/packet" 9 | 10 | var rulesp unsafe.Pointer 11 | 12 | const vecSize = 32 13 | 14 | func main() { 15 | flow.CheckFatal(flow.SystemInit(nil)) 16 | 17 | initCommonState() 18 | 19 | l3Rules, err := packet.GetL3ACLFromTextTable("rules2.conf") 20 | flow.CheckFatal(err) 21 | rulesp = unsafe.Pointer(l3Rules) 22 | go updateSeparateRules() 23 | 24 | firstFlow, err := flow.SetReceiver(0) 25 | flow.CheckFatal(err) 26 | outputFlows, err := flow.SetSplitter(firstFlow, mySplitter, flowN, nil) 27 | flow.CheckFatal(err) 28 | flow.CheckFatal(flow.SetStopper(outputFlows[0])) 29 | flow.CheckFatal(flow.SetVectorHandler(outputFlows[1], myHandler, nil)) 30 | for i := uint16(1); i < flowN; i++ { 31 | flow.CheckFatal(flow.SetHandler(outputFlows[i], modifyPacket[i-1], nil)) 32 | flow.CheckFatal(flow.SetSender(outputFlows[i], i-1)) 33 | } 34 | flow.CheckFatal(flow.SystemStart()) 35 | } 36 | 37 | func mySplitter(cur *packet.Packet, ctx flow.UserContext) uint { 38 | localL3Rules := (*packet.L3Rules)(atomic.LoadPointer(&rulesp)) 39 | return cur.L3ACLPort(localL3Rules) 40 | } 41 | 42 | func myHandler(curV []*packet.Packet, mask *[vecSize]bool, ctx flow.UserContext) { 43 | for i := uint(0); i < vecSize; i++ { 44 | if (*mask)[i] == true { 45 | cur := curV[i] 46 | cur.EncapsulateHead(types.EtherLen, types.IPv4MinLen) 47 | cur.ParseL3() 48 | cur.GetIPv4NoCheck().SrcAddr = types.BytesToIPv4(111, 22, 3, 0) 49 | cur.GetIPv4NoCheck().DstAddr = types.BytesToIPv4(3, 22, 111, 0) 50 | cur.GetIPv4NoCheck().VersionIhl = 0x45 51 | cur.GetIPv4NoCheck().NextProtoID = 0x04 52 | } 53 | } 54 | } 55 | 56 | func updateSeparateRules() { 57 | for { 58 | time.Sleep(time.Second * 5) 59 | locall3Rules, err := packet.GetL3ACLFromTextTable("rules2.conf") 60 | flow.CheckFatal(err) 61 | atomic.StorePointer(&rulesp, unsafe.Pointer(locall3Rules)) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /examples/tutorial/step11.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync/atomic" 4 | import "time" 5 | import "unsafe" 6 | import "github.com/intel-go/nff-go/types" 7 | import "github.com/intel-go/nff-go/flow" 8 | import "github.com/intel-go/nff-go/packet" 9 | 10 | var rulesp unsafe.Pointer 11 | 12 | const vecSize = 32 13 | 14 | func main() { 15 | flow.CheckFatal(flow.SystemInit(nil)) 16 | 17 | initCommonState() 18 | 19 | l3Rules, err := packet.GetL3ACLFromTextTable("rules2.conf") 20 | flow.CheckFatal(err) 21 | rulesp = unsafe.Pointer(l3Rules) 22 | go updateSeparateRules() 23 | 24 | firstFlow, err := flow.SetReceiver(0) 25 | flow.CheckFatal(err) 26 | outputFlows, err := flow.SetSplitter(firstFlow, mySplitter, flowN, nil) 27 | flow.CheckFatal(err) 28 | flow.CheckFatal(flow.SetStopper(outputFlows[0])) 29 | flow.CheckFatal(flow.SetVectorHandler(outputFlows[1], myHandler, nil)) 30 | for i := uint16(1); i < flowN; i++ { 31 | flow.CheckFatal(flow.SetHandler(outputFlows[i], modifyPacket[i-1], nil)) 32 | flow.CheckFatal(flow.SetSender(outputFlows[i], i-1)) 33 | } 34 | flow.CheckFatal(flow.SystemStart()) 35 | } 36 | 37 | func mySplitter(cur *packet.Packet, ctx flow.UserContext) uint { 38 | localL3Rules := (*packet.L3Rules)(atomic.LoadPointer(&rulesp)) 39 | return cur.L3ACLPort(localL3Rules) 40 | } 41 | 42 | func myHandler(curV []*packet.Packet, mask *[vecSize]bool, ctx flow.UserContext) { 43 | for i := uint(0); i < vecSize; i++ { 44 | if (*mask)[i] == true { 45 | cur := curV[i] 46 | cur.EncapsulateHead(types.EtherLen, types.IPv4MinLen) 47 | cur.ParseL3() 48 | cur.GetIPv4NoCheck().SrcAddr = types.BytesToIPv4(111, 22, 3, 0) 49 | cur.GetIPv4NoCheck().DstAddr = types.BytesToIPv4(3, 22, 111, 0) 50 | cur.GetIPv4NoCheck().VersionIhl = 0x45 51 | cur.GetIPv4NoCheck().NextProtoID = 0x04 52 | } 53 | } 54 | // Some heavy computational code 55 | heavyCode() 56 | } 57 | 58 | func heavyCode() { 59 | for i := 0; i < 1000000; i++ { 60 | } 61 | } 62 | 63 | func updateSeparateRules() { 64 | for { 65 | time.Sleep(time.Second * 5) 66 | locall3Rules, err := packet.GetL3ACLFromTextTable("rules2.conf") 67 | flow.CheckFatal(err) 68 | atomic.StorePointer(&rulesp, unsafe.Pointer(locall3Rules)) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /flow/predefined.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package flow is the main package of NFF-GO library and should be always imported by 6 | // user application. 7 | package flow 8 | 9 | import ( 10 | "github.com/intel-go/nff-go/common" 11 | "github.com/intel-go/nff-go/packet" 12 | "github.com/intel-go/nff-go/types" 13 | ) 14 | 15 | func handleARPICMPRequests(current *packet.Packet, context UserContext) bool { 16 | current.ParseL3() 17 | arp := current.GetARPCheckVLAN() 18 | // ARP can be only in IPv4. IPv6 replace it with modified ICMP 19 | if arp != nil { 20 | if packet.SwapBytesUint16(arp.Operation) != packet.ARPRequest || 21 | arp.THA != [types.EtherAddrLen]byte{} { 22 | return true 23 | } 24 | 25 | port := portPair[types.ArrayToIPv4(arp.TPA)] 26 | if port == nil { 27 | return true 28 | } 29 | 30 | // Prepare an answer to this request 31 | answerPacket, err := packet.NewPacket() 32 | if err != nil { 33 | common.LogFatal(common.Debug, err) 34 | } 35 | packet.InitARPReplyPacket(answerPacket, port.MAC, arp.SHA, types.ArrayToIPv4(arp.TPA), types.ArrayToIPv4(arp.SPA)) 36 | answerPacket.SendPacket(port.port) 37 | 38 | return false 39 | } 40 | ipv4 := current.GetIPv4() 41 | if ipv4 != nil { 42 | current.ParseL4ForIPv4() 43 | icmp := current.GetICMPForIPv4() 44 | if icmp != nil { 45 | // Check that received ICMP packet is echo request packet. 46 | if icmp.Type != types.ICMPTypeEchoRequest || icmp.Code != 0 { 47 | return true 48 | } 49 | 50 | // Check that received ICMP packet is addressed at this host. 51 | port := portPair[ipv4.DstAddr] 52 | if port == nil { 53 | return true 54 | } 55 | 56 | // Return a packet back to sender 57 | answerPacket, err := packet.NewPacket() 58 | if err != nil { 59 | common.LogFatal(common.Debug, err) 60 | } 61 | // TODO need to initilize new packet instead of copying 62 | packet.GeneratePacketFromByte(answerPacket, current.GetRawPacketBytes()) 63 | answerPacket.Ether.DAddr = current.Ether.SAddr 64 | answerPacket.Ether.SAddr = current.Ether.DAddr 65 | answerPacket.ParseL3() 66 | (answerPacket.GetIPv4NoCheck()).DstAddr = ipv4.SrcAddr 67 | (answerPacket.GetIPv4NoCheck()).SrcAddr = ipv4.DstAddr 68 | answerPacket.ParseL4ForIPv4() 69 | (answerPacket.GetICMPNoCheck()).Type = types.ICMPTypeEchoResponse 70 | ipv4.HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(ipv4)) 71 | answerPacket.ParseL7(types.ICMPNumber) 72 | (answerPacket.GetICMPNoCheck()).Cksum = packet.SwapBytesUint16( 73 | packet.CalculateIPv4ICMPChecksum( 74 | answerPacket.GetIPv4NoCheck(), 75 | answerPacket.GetICMPNoCheck(), 76 | answerPacket.Data)) 77 | 78 | answerPacket.SendPacket(port.port) 79 | 80 | return false 81 | } 82 | } 83 | return true 84 | } 85 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/intel-go/nff-go 2 | 3 | require ( 4 | github.com/docker/distribution v2.8.0 // indirect 5 | github.com/docker/docker v1.13.1 6 | github.com/docker/go-connections v0.4.0 7 | github.com/docker/go-units v0.3.3 // indirect 8 | github.com/flier/gohs v1.0.0 9 | github.com/google/gopacket v1.1.16 // indirect 10 | github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect 11 | github.com/opencontainers/go-digest v1.0.0-rc1 // indirect 12 | github.com/pkg/errors v0.8.1 13 | github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 // indirect 14 | github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c // indirect 15 | github.com/vishvananda/netlink v1.0.0 // indirect 16 | github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect 17 | golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect 18 | golang.org/x/sys v0.0.0-20190204203706-41f3e6584952 // indirect 19 | golang.org/x/tools v0.0.0-20190205201329-379209517ffe // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /internal/low/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | include $(PATH_TO_MK)/include.mk 7 | 8 | .PHONY: testing 9 | testing: check-pktgen 10 | go test -v -tags "${GO_BUILD_TAGS}" 11 | -------------------------------------------------------------------------------- /internal/low/low_bpf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build bpf 6 | 7 | package low 8 | 9 | /* 10 | #cgo LDFLAGS: -lbpf -lelf 11 | */ 12 | import "C" 13 | -------------------------------------------------------------------------------- /internal/low/low_mlx.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build mlx 6 | 7 | package low 8 | 9 | /* 10 | #cgo LDFLAGS: -lrte_distributor -lrte_reorder -lrte_kni -lrte_pipeline -lrte_table -lrte_port -lrte_timer -lrte_jobstats -lrte_lpm -lrte_power -lrte_acl -lrte_meter -lrte_sched -lrte_vhost -lrte_ip_frag -lrte_cfgfile -Wl,--whole-archive -Wl,--start-group -lrte_kvargs -lrte_mbuf -lrte_hash -lrte_ethdev -lrte_mempool -lrte_ring -lrte_mempool_ring -lrte_eal -lrte_cmdline -lrte_net -lrte_bus_pci -lrte_pci -lrte_bus_vdev -lrte_timer -lrte_pmd_bond -lrte_pmd_vmxnet3_uio -lrte_pmd_virtio -lrte_pmd_cxgbe -lrte_pmd_enic -lrte_pmd_i40e -lrte_pmd_fm10k -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ena -lrte_pmd_ring -lrte_pmd_af_packet -lrte_pmd_null -libverbs -lmnl -lmlx4 -lmlx5 -lrte_pmd_mlx4 -lrte_pmd_mlx5 -Wl,--end-group -Wl,--no-whole-archive -lrt -lm -ldl -lnuma 11 | */ 12 | import "C" 13 | -------------------------------------------------------------------------------- /internal/low/low_no_mlx.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !mlx 6 | 7 | package low 8 | 9 | /* 10 | #cgo LDFLAGS: -lrte_distributor -lrte_reorder -lrte_kni -lrte_pipeline -lrte_table -lrte_port -lrte_timer -lrte_jobstats -lrte_lpm -lrte_power -lrte_acl -lrte_meter -lrte_sched -lrte_vhost -lrte_ip_frag -lrte_cfgfile -Wl,--whole-archive -Wl,--start-group -lrte_kvargs -lrte_mbuf -lrte_hash -lrte_ethdev -lrte_mempool -lrte_ring -lrte_mempool_ring -lrte_eal -lrte_cmdline -lrte_net -lrte_bus_pci -lrte_pci -lrte_bus_vdev -lrte_timer -lrte_pmd_bond -lrte_pmd_vmxnet3_uio -lrte_pmd_virtio -lrte_pmd_cxgbe -lrte_pmd_enic -lrte_pmd_i40e -lrte_pmd_fm10k -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ena -lrte_pmd_ring -lrte_pmd_af_packet -lrte_pmd_null -Wl,--end-group -Wl,--no-whole-archive -lrt -lm -ldl -lnuma 11 | */ 12 | import "C" 13 | -------------------------------------------------------------------------------- /internal/low/low_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package low 6 | 7 | import ( 8 | "log" 9 | "math/rand" 10 | "testing" 11 | "time" 12 | "unsafe" 13 | ) 14 | 15 | func init() { 16 | argc, argv := InitDPDKArguments([]string{}) 17 | // Default: burstSize=32, mbufNumber=8191, mbufCacheSize=250 18 | if err := InitDPDK(argc, argv, 32, 8191, 250, 0, false, false, false, false); err != nil { 19 | log.Fatalf("fail to initialize with error: %+v\n", err) 20 | } 21 | rand.Seed(time.Now().UTC().UnixNano()) 22 | } 23 | 24 | func TestReorder(t *testing.T) { 25 | const sliceLength = 500 26 | input := make([]int, sliceLength, sliceLength) 27 | inputPointers := make([]uintptr, sliceLength, sliceLength) 28 | outputPointers := make([]uintptr, sliceLength, sliceLength) 29 | 30 | for i := 0; i < sliceLength; i++ { 31 | input[i] = i 32 | inputPointers[i] = uintptr(unsafe.Pointer(&input[i])) 33 | } 34 | 35 | // Real usable ring size is count-1 36 | ring := CreateRing(64) 37 | a1 := uint(63) 38 | a2 := uint(29) 39 | a3 := uint(14) 40 | a4 := uint(1) 41 | for k := 0; k < 100; k++ { 42 | if k != 0 { 43 | a1 = uint(rand.Intn(64)) 44 | a2 = uint(rand.Intn(64)) 45 | a3 = uint(rand.Intn(64)) 46 | a4 = uint(rand.Intn(int(64 - a3))) 47 | } 48 | for j := 0; j < 1000; j++ { 49 | if ring.EnqueueBurst(inputPointers[:a1], a1) != a1 { 50 | t.Errorf("Incorrect enqueueBurst 1") 51 | } 52 | if ring.DequeueBurst(outputPointers[:a1], a1) != a1 { 53 | t.Errorf("Incorrect dequeueBurst 1") 54 | } 55 | if ring.EnqueueBurst(inputPointers[a1:a1+a2], a2) != a2 { 56 | t.Errorf("Incorrect enqueueBurst 2") 57 | } 58 | if ring.DequeueBurst(outputPointers[a1:a1+a2], a2) != a2 { 59 | t.Errorf("Incorrect dequeueBurst 2") 60 | } 61 | if ring.EnqueueBurst(inputPointers[a1+a2:a1+a2+a3], a3) != a3 { 62 | t.Errorf("Incorrect enqueueBurst 3") 63 | } 64 | if ring.EnqueueBurst(inputPointers[a1+a2+a3:a1+a2+a3+a4], a4) != a4 { 65 | t.Errorf("Incorrect enqueueBurst 4") 66 | } 67 | if ring.DequeueBurst(outputPointers[a1+a2:a1+a2+a3+a4], a3+a4) != a3+a4 { 68 | t.Errorf("Incorrect dequeueBurst 3") 69 | } 70 | for i := 0; i < int(a1+a2+a3+a4); i++ { 71 | if *(*int)(unsafe.Pointer(outputPointers[i])) != i { 72 | t.Errorf("Ring reorder packet. %d element is %d instead of %d.", i, *(*int)(unsafe.Pointer(outputPointers[i])), i) 73 | t.FailNow() 74 | } 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /mk/include.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | .DEFAULT_GOAL := all 6 | 7 | PROJECT_ROOT := $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/..) 8 | 9 | # Main DPDK variables 10 | DPDK_DIR=dpdk 11 | PKTGEN_DIR=pktgen-dpdk 12 | export RTE_TARGET=x86_64-native-linuxapp-gcc 13 | DPDK_INSTALL_DIR=$(RTE_TARGET)-install 14 | export RTE_SDK=$(PROJECT_ROOT)/dpdk/$(DPDK_DIR)/$(DPDK_INSTALL_DIR)/usr/local/share/dpdk 15 | 16 | # Configure flags for native code. Disable FSGSBASE and F16C to run in 17 | # VMs and Docker containers. 18 | CFLAGS = -I$(RTE_SDK)/$(RTE_TARGET)/include \ 19 | -O3 \ 20 | -std=gnu11 \ 21 | -m64 \ 22 | -pthread \ 23 | -march=native \ 24 | -mno-fsgsbase \ 25 | -mno-f16c \ 26 | -DRTE_MACHINE_CPUFLAG_SSE \ 27 | -DRTE_MACHINE_CPUFLAG_SSE2 \ 28 | -DRTE_MACHINE_CPUFLAG_SSE3 \ 29 | -DRTE_MACHINE_CPUFLAG_SSSE3 \ 30 | -DRTE_MACHINE_CPUFLAG_SSE4_1 \ 31 | -DRTE_MACHINE_CPUFLAG_SSE4_2 \ 32 | -DRTE_MACHINE_CPUFLAG_PCLMULQDQ \ 33 | -DRTE_MACHINE_CPUFLAG_RDRAND \ 34 | -DRTE_MACHINE_CPUFLAG_F16C \ 35 | -include rte_config.h \ 36 | -Wno-deprecated-declarations 37 | 38 | ifdef NFF_GO_DEBUG 39 | export CFLAGS += -g -O0 -D DEBUG 40 | endif 41 | 42 | HAVE_AVX2 := $(shell grep avx2 /proc/cpuinfo) 43 | ifdef HAVE_AVX2 44 | $(info Checking for AVX support... AVX and AVX2) 45 | CFLAGS += -DRTE_MACHINE_CPUFLAG_AVX -DRTE_MACHINE_CPUFLAG_AVX2 46 | else 47 | HAVE_AVX := $(shell grep avx /proc/cpuinfo) 48 | ifdef HAVE_AVX 49 | $(info Checking for AVX support... AVX) 50 | CFLAGS += -DRTE_MACHINE_CPUFLAG_AVX 51 | else 52 | $(info Checking for AVX support... no) 53 | endif 54 | endif 55 | 56 | ifndef NFF_GO_NO_MLX_DRIVERS 57 | ifeq (,$(findstring mlx,$(GO_BUILD_TAGS))) 58 | export GO_BUILD_TAGS += mlx 59 | endif 60 | endif 61 | 62 | ifndef NFF_GO_NO_BPF_SUPPORT 63 | ifeq (,$(findstring bpf,$(GO_BUILD_TAGS))) 64 | export GO_BUILD_TAGS += bpf 65 | endif 66 | CFLAGS += -DNFF_GO_SUPPORT_XDP 67 | endif 68 | 69 | export CGO_CFLAGS = $(CFLAGS) 70 | 71 | export CGO_LDFLAGS = \ 72 | -L$(RTE_SDK)/$(RTE_TARGET)/lib \ 73 | -Wl,--no-as-needed \ 74 | -Wl,-export-dynamic 75 | 76 | export CGO_LDFLAGS_ALLOW=-Wl,--((no-)?whole-archive|((start|end)-group)) 77 | 78 | # Universal check whether a variable is set 79 | .PHONY: .check-defined-% 80 | .check-defined-%: 81 | @if [ -z '${${*}}' ]; then echo "!!! Variable $* is undefined" && exit 1; fi 82 | 83 | check-pktgen: 84 | @if [ ! -f $(PROJECT_ROOT)/dpdk/pktgen ]; then \ 85 | echo "!!! It is necessary to build DPDK before building any parts of NFF-GO." && \ 86 | echo "!!! Please run make at the project root or in dpdk subdirectory" && \ 87 | exit 1; \ 88 | fi 89 | -------------------------------------------------------------------------------- /mk/intermediate.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | TARGETS = all clean images clean-images deploy cleanall 6 | .PHONY: $(TARGETS) $(SUBDIRS) 7 | 8 | $(TARGETS): $(SUBDIRS) 9 | 10 | included_from_dir := $(shell basename $(dir $(abspath $(word 1, $(MAKEFILE_LIST))))) 11 | @eval $(included_from_dir): all 12 | 13 | targets_to_execute := $(filter-out $(included_from_dir), $(MAKECMDGOALS)) 14 | 15 | $(SUBDIRS): 16 | $(MAKE) -C $@ $(targets_to_execute) 17 | -------------------------------------------------------------------------------- /mk/leaf.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | include $(PATH_TO_MK)/include.mk 6 | 7 | # Always rebuild all tests and examples because changes in the library aren't tracked now 8 | .PHONY: $(EXECUTABLES) 9 | 10 | # Build all 11 | .PHONY: clean 12 | 13 | ifdef NFF_GO_DEBUG 14 | # Flags to build Go files without optimizations 15 | export GO_COMPILE_FLAGS += -gcflags=all='-N -l' 16 | endif 17 | 18 | $(EXECUTABLES) : % : %.go 19 | go build $(GO_COMPILE_FLAGS) -tags "${GO_BUILD_TAGS}" $< $(COMMON_FILES) 20 | 21 | ifndef NOCHECK_PKTGEN 22 | all: check-pktgen 23 | endif 24 | all: $(EXECUTABLES) 25 | 26 | clean-default: 27 | -rm $(EXECUTABLES) 28 | 29 | clean: clean-default 30 | 31 | # Local docker targets 32 | .PHONY: .check-images-env images clean-images 33 | 34 | # Add user name to generated images 35 | ifdef NFF_GO_IMAGE_PREFIX 36 | WORKIMAGENAME=$(NFF_GO_IMAGE_PREFIX)/$(USER)/$(IMAGENAME) 37 | IMAGE_PREFIX=$(NFF_GO_IMAGE_PREFIX)/$(USER) 38 | else 39 | WORKIMAGENAME=$(USER)/$(IMAGENAME) 40 | IMAGE_PREFIX=$(USER) 41 | endif 42 | 43 | .check-images-env: .check-defined-IMAGENAME 44 | 45 | images: Dockerfile .check-images-env all 46 | docker build --build-arg USER_NAME=$(IMAGE_PREFIX) -t $(WORKIMAGENAME) . 47 | 48 | clean-images: .check-images-env clean 49 | -docker rmi $(WORKIMAGENAME) 50 | 51 | # Distributed docker targets 52 | .PHONY: .check-deploy-env deploy cleanall 53 | 54 | .check-deploy-env: .check-defined-NFF_GO_HOSTS 55 | 56 | deploy: .check-deploy-env images 57 | $(eval TMPNAME=tmp-$(IMAGENAME).tar) 58 | docker save $(WORKIMAGENAME) > $(TMPNAME) 59 | for host in `echo $(NFF_GO_HOSTS) | tr ',' ' '`; do \ 60 | echo Uploading $(WORKIMAGENAME) to $$host; \ 61 | if ! docker -H tcp://$$host load < $(TMPNAME); then break; fi; \ 62 | done 63 | rm $(TMPNAME) 64 | 65 | cleanall: .check-deploy-env clean-images 66 | -for host in `echo $(NFF_GO_HOSTS) | tr ',' ' '`; do \ 67 | docker -H tcp://$$host rmi -f $(WORKIMAGENAME); \ 68 | done 69 | -------------------------------------------------------------------------------- /nff-go-base/.gitignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /nff-go-base/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../mk 6 | IMAGENAME = nff-go-base 7 | EXECUTABLES = 8 | NOCHECK_PKTGEN = yes 9 | 10 | # This will not be used from "make deploy" or "make images" by default 11 | # You should change images rule in mk/leaf.mk from "Dockerfile" to "Fedora" 12 | Fedora: Makefile 13 | echo 'ARG USER_NAME' > Dockerfile 14 | echo 'FROM fedora' >> Dockerfile 15 | if [ -n '${http_proxy}' ]; then \ 16 | echo 'ENV http_proxy ${http_proxy}' >> Dockerfile; \ 17 | echo 'ENV https_proxy ${https_proxy}' >> Dockerfile; \ 18 | echo 'RUN echo proxy=${http_proxy} >> /etc/dnf/dnf.conf' >> Dockerfile; \ 19 | fi 20 | echo 'RUN dnf -y install git numactl-libs.x86_64 lua-devel libmnl-devel rdma-core-devel libibverbs; dnf clean all' >> Dockerfile 21 | echo 'RUN git clone https://github.com/libbpf/libbpf && make -C libbpf/src all install && echo "/usr/lib64" > /etc/ld.so.conf.d/usrlib64.conf && ldconfig' >> Dockerfile 22 | echo 'CMD ["/bin/bash"]' >> Dockerfile 23 | 24 | Dockerfile: Makefile 25 | echo 'ARG USER_NAME' > Dockerfile 26 | echo 'FROM ubuntu:disco' >> Dockerfile 27 | if [ -n '${http_proxy}' ]; then \ 28 | echo 'ENV http_proxy ${http_proxy}' >> Dockerfile; \ 29 | echo 'ENV https_proxy ${https_proxy}' >> Dockerfile; \ 30 | echo 'RUN echo Acquire::http::Proxy \"${http_proxy}\"\; >> /etc/apt/apt.conf' >> Dockerfile; \ 31 | echo 'RUN echo Acquire::https::Proxy \"${https_proxy}\"\; >> /etc/apt/apt.conf' >> Dockerfile; \ 32 | fi 33 | echo 'RUN apt-get update; apt-get install -y git pciutils libnuma-dev libpcap0.8-dev liblua5.3-dev libibverbs-dev libmnl-dev libelf-dev; apt-get clean all' >> Dockerfile 34 | echo 'RUN git clone -b v0.0.4 https://github.com/libbpf/libbpf && make -C libbpf/src all install && echo "/usr/lib64" > /etc/ld.so.conf.d/usrlib64.conf && ldconfig' >> Dockerfile 35 | echo 'CMD ["/bin/bash"]' >> Dockerfile 36 | 37 | .PHONY: dpdk 38 | dpdk: 39 | 40 | include $(PATH_TO_MK)/leaf.mk 41 | -------------------------------------------------------------------------------- /packet/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../mk 6 | include $(PATH_TO_MK)/include.mk 7 | 8 | .PHONY: testing 9 | testing: check-pktgen 10 | go test -tags "${GO_BUILD_TAGS}" 11 | 12 | .PHONY: coverage 13 | coverage: 14 | go test -cover -coverprofile=c.out 15 | go tool cover -html=c.out -o packet_coverage.html 16 | -------------------------------------------------------------------------------- /packet/gre.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package packet 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/intel-go/nff-go/types" 11 | ) 12 | 13 | type GREHdr struct { 14 | Flags uint16 15 | NextProto uint16 16 | } 17 | 18 | func (hdr *GREHdr) String() string { 19 | return fmt.Sprintf("GRE: flags = 0x%04x, embedded protocol = 0x%04x", 20 | hdr.Flags, hdr.NextProto) 21 | } 22 | 23 | // GetGREForIPv4 casts L4 pointer to *GREHdr type. 24 | func (packet *Packet) GetGREForIPv4() *GREHdr { 25 | if packet.GetIPv4NoCheck().NextProtoID == types.GRENumber { 26 | return (*GREHdr)(packet.L4) 27 | } 28 | return nil 29 | } 30 | 31 | // GetGRENoCheck casts L4 pointer to *GREHdr type. 32 | func (packet *Packet) GetGRENoCheck() *GREHdr { 33 | return (*GREHdr)(packet.L4) 34 | } 35 | -------------------------------------------------------------------------------- /packet/mpls_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package packet 6 | 7 | import ( 8 | "encoding/hex" 9 | "testing" 10 | ) 11 | 12 | func init() { 13 | tInitDPDK() 14 | } 15 | 16 | func TestAllMpls(t *testing.T) { 17 | // From pktgen 18 | buf, _ := hex.DecodeString("6805ca3331386805ca3332688847fffffb394500002a6bf500000406c886c0a80001c0a8010104d2162e123456781234569050102000f0dd00003031") 19 | current := getPacket() 20 | GeneratePacketFromByte(current, buf) 21 | 22 | m := current.GetMPLSNoCheck() 23 | internalTest(m, t, 1048575, 5, 1, 57) 24 | if m.DecreaseTTL() != true { 25 | t.Errorf("Decrease from 57 shouldn't return false") 26 | } 27 | internalTest(m, t, 1048575, 5, 1, 56) 28 | label := m.GetMPLSLabel() 29 | if label != 1048575 { 30 | t.Errorf("Incorrect result:\ngot: %d, \nwant: %d\n\n", label, 1048575) 31 | } 32 | label = label - 2 33 | m.SetMPLSLabel(label) 34 | internalTest(m, t, 1048573, 5, 1, 56) 35 | current.RemoveMPLS() 36 | newMPLS := uint32(0x11111a01) 37 | current.AddMPLS(newMPLS) 38 | internalTest(m, t, 69905, 5, 0, 1) 39 | if m.DecreaseTTL() != false { 40 | t.Errorf("Decrease from 0 should return false to discard this packet") 41 | } 42 | } 43 | 44 | func internalTest(m *MPLSHdr, t *testing.T, label uint32, exp uint32, s uint32, ttl uint32) { 45 | if SwapBytesUint32(m.mpls)>>12 != label { 46 | t.Errorf("Incorrect result:\ngot: %d, \nwant: %d\n\n", SwapBytesUint32(m.mpls)>>12, label) 47 | } 48 | if (SwapBytesUint32(m.mpls)>>9)&0x00000007 != exp { 49 | t.Errorf("Incorrect result:\ngot: %d, \nwant: %d\n\n", (SwapBytesUint32(m.mpls)>>9)&0x00000007, exp) 50 | } 51 | if (SwapBytesUint32(m.mpls)>>8)&1 != s { 52 | t.Errorf("Incorrect result:\ngot: %d, \nwant: %d\n\n", (SwapBytesUint32(m.mpls)>>8)&1, s) 53 | } 54 | if SwapBytesUint32(m.mpls)&0x000000ff != ttl { 55 | t.Errorf("Incorrect result:\ngot: %d, \nwant: %d\n\n", SwapBytesUint32(m.mpls)&0x000000ff, ttl) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /scripts/get-depends.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -x 2 | 3 | go get -v -d github.com/docker/docker/client 4 | rm -rf $GOPATH/src/github.com/docker/docker/vendor/github.com/docker/go-connections 5 | go get -v github.com/Sirupsen/logrus 6 | go get -v github.com/pkg/errors 7 | go get -v golang.org/x/net/proxy 8 | go get -v github.com/docker/go-connections 9 | go get -v github.com/vishvananda/netlink 10 | go get -v github.com/google/gopacket 11 | 12 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../mk 6 | SUBDIRS = stability performance stash framework 7 | .PHONY: perf_testing 8 | 9 | include $(PATH_TO_MK)/intermediate.mk 10 | -------------------------------------------------------------------------------- /test/framework/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aregm/nff-go/3fcc11eab4030598949f7e34be99ed8f70221e08/test/framework/.gitignore -------------------------------------------------------------------------------- /test/framework/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | SUBDIRS = main 7 | 8 | main: 9 | 10 | %_string.go: types.go 11 | go generate 12 | 13 | testing: 14 | go test -v 15 | 16 | include $(PATH_TO_MK)/intermediate.mk 17 | -------------------------------------------------------------------------------- /test/framework/apptype_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=AppType,TestType,TestStatus types.go"; DO NOT EDIT. 2 | 3 | package test 4 | 5 | import "strconv" 6 | 7 | const _AppType_name = "TestAppGoTestAppPktgenTestAppApacheBenchmarkTestAppLatencyTestAppWrkBenchmark" 8 | 9 | var _AppType_index = [...]uint8{0, 9, 22, 44, 58, 77} 10 | 11 | func (i AppType) String() string { 12 | if i < 0 || i >= AppType(len(_AppType_index)-1) { 13 | return "AppType(" + strconv.FormatInt(int64(i), 10) + ")" 14 | } 15 | return _AppType_name[_AppType_index[i]:_AppType_index[i+1]] 16 | } 17 | 18 | const _TestType_name = "TestTypeBenchmarkTestTypeScenarioTestTypeApacheBenchmarkTestTypeLatencyTestTypeWrkBenchmark" 19 | 20 | var _TestType_index = [...]uint8{0, 17, 33, 56, 71, 91} 21 | 22 | func (i TestType) String() string { 23 | if i < 0 || i >= TestType(len(_TestType_index)-1) { 24 | return "TestType(" + strconv.FormatInt(int64(i), 10) + ")" 25 | } 26 | return _TestType_name[_TestType_index[i]:_TestType_index[i+1]] 27 | } 28 | 29 | const _TestStatus_name = "TestCreatedTestInitializedTestInvalidTestRunningTestReportedPassedTestReportedFailedTestTimedOutTestInterrupted" 30 | 31 | var _TestStatus_index = [...]uint8{0, 11, 26, 37, 48, 66, 84, 96, 111} 32 | 33 | func (i TestStatus) String() string { 34 | if i < 0 || i >= TestStatus(len(_TestStatus_index)-1) { 35 | return "TestStatus(" + strconv.FormatInt(int64(i), 10) + ")" 36 | } 37 | return _TestStatus_name[_TestStatus_index[i]:_TestStatus_index[i+1]] 38 | } 39 | -------------------------------------------------------------------------------- /test/framework/main/.gitignore: -------------------------------------------------------------------------------- 1 | tf 2 | perf_compare 3 | report_compare 4 | 2018* 5 | -------------------------------------------------------------------------------- /test/framework/main/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | % : %.go 6 | go build $< 7 | 8 | all: tf perf_compare report_compare 9 | 10 | tf: tf.go ../apptype_string.go ../config.go ../dockerlauncher.go ../logging.go ../testsuite.go ../types.go ../report.go 11 | 12 | report_compare: report_compare.go ../types.go ../report.go ../dockerlauncher.go 13 | 14 | clean: 15 | -rm tf perf_compare 16 | 17 | images: all 18 | deploy: all 19 | clean-images: clean 20 | cleanall: clean 21 | -------------------------------------------------------------------------------- /test/framework/main/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "hostname1": [ 3 | "52:54:00:19:85:98", 4 | "52:54:00:66:84:C1" 5 | ], 6 | "hostname2": [ 7 | "52:54:00:6E:38:53", 8 | "52:54:00:A0:79:CF" 9 | ] 10 | } -------------------------------------------------------------------------------- /test/framework/main/perf_compare.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | package main 5 | 6 | import ( 7 | "bufio" 8 | "fmt" 9 | "math" 10 | "os" 11 | "strconv" 12 | "strings" 13 | ) 14 | 15 | func main() { 16 | if len(os.Args) != 2 { 17 | fmt.Println("should have one argument for a directory with test results") 18 | os.Exit(1) 19 | } 20 | currentFile := os.Args[1] + "/index.html" 21 | 22 | i := 0 23 | s := 0 24 | global_off := 1.0 25 | global_on := 1.0 26 | global_cores := 1.0 27 | geomean := 0.0 28 | 29 | file, err := os.Open(currentFile) 30 | if err != nil { 31 | fmt.Println("Can't open", currentFile) 32 | os.Exit(1) 33 | } 34 | defer file.Close() 35 | 36 | var lines []string 37 | scanner := bufio.NewScanner(file) 38 | for scanner.Scan() { 39 | lines = append(lines, scanner.Text()) 40 | } 41 | for i < len(lines) { 42 | if strings.Contains(lines[i], "onclick=\"toggleVisibility") { 43 | i++ 44 | name := strings.Split(lines[i][8:], "_off_") 45 | if len(name[1]) == 2 { 46 | name[1] = " " + name[1] 47 | } else if len(name[1]) == 3 { 48 | name[1] = " " + name[1] 49 | } 50 | j := i + 1 51 | for strings.Contains(lines[j], "Average") == false { 52 | j++ 53 | } 54 | t := strings.Split(lines[j], "")[1] 55 | off_MGB, _ := strconv.Atoi(t[:len(t)-5]) // -6 ? 56 | t = strings.Split(lines[j+1], "")[0] 57 | off_cores, _ := strconv.Atoi(t[40:]) 58 | k := j + 1 59 | for strings.Contains(lines[k], "Average") == false { 60 | k++ 61 | } 62 | t = strings.Split(lines[k], "")[1] 63 | on_MGB, _ := strconv.Atoi(t[:len(t)-5]) // -6 ? 64 | t = strings.Split(lines[k+1], "")[0] 65 | on_cores, _ := strconv.Atoi(t[40:]) 66 | 67 | if (s < 9 && s%3 == 0) || (s >= 9 && (s-9)%4 == 0) { 68 | fmt.Println("--------", name[0], name[1], "off:", off_MGB, "on:", on_MGB, "off_cores:", off_cores, "on_cores:", on_cores, "--------") 69 | } else { 70 | fmt.Println(" ", name[0], name[1], "off:", off_MGB, "on:", on_MGB, "off_cores:", off_cores, "on_cores:", on_cores) 71 | } 72 | global_off = global_off * float64(off_MGB) 73 | global_on = global_on * float64(on_MGB) 74 | global_cores = global_cores * float64(on_cores) 75 | geomean++ 76 | i = k + 1 77 | s = s + 1 78 | } else { 79 | i++ 80 | } 81 | } 82 | fmt.Println("Overall geomean off:", math.Pow(global_off, 1.0/geomean), "on:", math.Pow(global_on, 1.0/geomean), "cores:", math.Pow(global_cores, 1.0/geomean)) 83 | } 84 | -------------------------------------------------------------------------------- /test/framework/main/tf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/intel-go/nff-go/test/framework" 8 | 9 | import ( 10 | "flag" 11 | "os" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | var hl test.HostsList 17 | var vl test.VariablesList = test.VariablesList{} 18 | var tl test.TestsList 19 | 20 | func main() { 21 | test.SetLogLevel(test.LogDebugLvl) 22 | var configFile string 23 | var directory string 24 | 25 | flag.Var(&hl, "hosts", "Comma-separated list of `host:port,host:port...host:port` pairs to override settings in config file, e.g. \"-hosts host1:2375,host2:2376\".") 26 | flag.Var(&vl, "var", "Variables listed in form NAME=VALUE. Variables are replaced in tests command lines in form NAME substring is replaced with VALUE. If whole paramenters becomes an empty string it is deleted entirely from command line. Multiple -var flags are allowed. Command line replacement order is not defined.") 27 | flag.Var(&tl, "test", "Testcase regexp to execute. Test is executed if regexp matches test name substring. Multiple -test flags are allowed. If no -test flag is specified, all testcases in config file are executed.") 28 | flag.StringVar(&configFile, "config", "config.json", "Name of config file to use") 29 | flag.StringVar(&directory, "directory", "", "Use `directory` to output log files instead of timestamp") 30 | flag.BoolVar(&test.NoDeleteContainersOnExit, "nodelete", false, "Do not remove containers after tests finish") 31 | repeatFailed := flag.Int("repeat-failed", 1, "Number of times to repeat a test which failed. This includes tests that timed out.") 32 | flag.Parse() 33 | 34 | // Read config 35 | config, err := test.ReadConfig(configFile, hl, vl) 36 | if err != nil { 37 | test.LogPanic(err) 38 | } 39 | test.LogDebug(config) 40 | 41 | if directory == "" { 42 | directory = strings.Replace(time.Now().Format(time.RFC3339), ":", "\ua789", -1) 43 | } 44 | err = os.Mkdir(directory, os.ModeDir|os.ModePerm) 45 | if err != nil { 46 | test.LogPanic(err) 47 | } 48 | 49 | // Start test execution 50 | status := config.RunAllTests(directory, tl, *repeatFailed) 51 | os.Exit(status) 52 | } 53 | -------------------------------------------------------------------------------- /test/performance/.gitignore: -------------------------------------------------------------------------------- 1 | perf_light 2 | perf_main 3 | perf_seq 4 | ipsec 5 | latency 6 | perf_gen 7 | perf_count 8 | -------------------------------------------------------------------------------- /test/performance/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY perf_light . 12 | COPY perf_main . 13 | COPY perf_seq . 14 | COPY ipsec . 15 | COPY latency . 16 | COPY perf_gen . 17 | COPY perf_count . 18 | -------------------------------------------------------------------------------- /test/performance/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | IMAGENAME = nff-go-performance 7 | EXECUTABLES = perf_light perf_main perf_seq ipsec latency perf_gen perf_count 8 | 9 | include $(PATH_TO_MK)/leaf.mk 10 | -------------------------------------------------------------------------------- /test/performance/perf_count.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "sync/atomic" 11 | "time" 12 | 13 | "github.com/intel-go/nff-go/flow" 14 | "github.com/intel-go/nff-go/packet" 15 | ) 16 | 17 | var received uint64 18 | 19 | type ctx struct { 20 | received uint64 21 | } 22 | 23 | var ccc []*uint64 24 | 25 | func (c ctx) Copy() interface{} { 26 | n := new(ctx) 27 | ccc = append(ccc, &(n.received)) 28 | return n 29 | } 30 | 31 | func (c ctx) Delete() { 32 | } 33 | 34 | func main() { 35 | inport := flag.Uint("inport", 0, "port for receiver") 36 | s := flag.Uint("size", 64, "size of packets") 37 | flag.Parse() 38 | 39 | config := flow.Config{ 40 | StopOnDedicatedCore: true, 41 | } 42 | flow.CheckFatal(flow.SystemInit(&config)) 43 | 44 | firstFlow, err := flow.SetReceiver(uint16(*inport)) 45 | flow.CheckFatal(err) 46 | 47 | go report(uint64(*s)) 48 | 49 | flow.CheckFatal(flow.SetVectorHandler(firstFlow, count, *new(ctx))) 50 | flow.CheckFatal(flow.SetStopper(firstFlow)) 51 | 52 | flow.CheckFatal(flow.SystemStart()) 53 | } 54 | 55 | func count(currentPacket []*packet.Packet, mask *[32]bool, context flow.UserContext) { 56 | var i uint64 57 | for i = 0; i < 32; i++ { 58 | if mask[i] == false { 59 | break 60 | } 61 | } 62 | ctx1 := context.(*ctx) 63 | atomic.AddUint64(&(ctx1.received), i) 64 | } 65 | 66 | func report(size uint64) { 67 | for { 68 | time.Sleep(time.Second) 69 | var number uint64 70 | for i := 0; i < len(ccc); i++ { 71 | number += atomic.LoadUint64(ccc[i]) 72 | atomic.StoreUint64(ccc[i], 0) 73 | } 74 | fmt.Println("Output: Packets/sec:", number, "Mbits/sec:", number*8*(size+20)/1000/1000) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /test/performance/perf_gen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "github.com/intel-go/nff-go/flow" 10 | "github.com/intel-go/nff-go/packet" 11 | "github.com/intel-go/nff-go/types" 12 | ) 13 | 14 | var size uint 15 | var speed uint 16 | 17 | type ctx struct { 18 | r uint16 19 | } 20 | 21 | func (c ctx) Copy() interface{} { 22 | n := new(ctx) 23 | n.r = 20 24 | return n 25 | } 26 | 27 | func (c ctx) Delete() { 28 | } 29 | 30 | func main() { 31 | flag.UintVar(&size, "s", 64, "size of packets") 32 | flag.UintVar(&speed, "v", 40000, "speed of generation") 33 | flag.Parse() 34 | 35 | pkts := uint64(speed * 1000 * 1000 / 8 / (size + 20)) 36 | size = size - types.EtherLen - types.IPv4MinLen - types.TCPMinLen - 4 /* Ethernet checksum length*/ 37 | 38 | flow.SystemInit(nil) 39 | 40 | a, _, _ := flow.SetFastGenerator(generatePacket, pkts/2, *new(ctx)) 41 | b, _, _ := flow.SetFastGenerator(generatePacket, pkts/2, *new(ctx)) 42 | 43 | flow.SetSender(a, 0) 44 | flow.SetSender(b, 0) 45 | 46 | flow.SystemStart() 47 | } 48 | 49 | // Function to use in generator 50 | func generatePacket(pkt *packet.Packet, context flow.UserContext) { 51 | ctx1 := context.(*ctx) 52 | r := ctx1.r 53 | packet.InitEmptyIPv4TCPPacket(pkt, size) 54 | ipv4 := pkt.GetIPv4() 55 | tcp := pkt.GetTCPForIPv4() 56 | 57 | ipv4.DstAddr = packet.SwapBytesIPv4Addr(types.IPv4Address(r)) 58 | ipv4.SrcAddr = packet.SwapBytesIPv4Addr(types.IPv4Address(r + 15)) 59 | 60 | tcp.DstPort = packet.SwapBytesUint16(r + 25) 61 | tcp.SrcPort = packet.SwapBytesUint16(r + 35) 62 | 63 | ctx1.r++ 64 | if ctx1.r > 259 { 65 | ctx1.r = 20 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/performance/perf_light.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | ) 13 | 14 | func main() { 15 | var mode uint 16 | flag.UintVar(&mode, "mode", 0, "Benching mode: 0 - empty, 1 - parsing, 2 - parsing, reading, writing") 17 | outport := flag.Uint("outport", 1, "port for sender") 18 | inport := flag.Uint("inport", 0, "port for receiver") 19 | noscheduler := flag.Bool("no-scheduler", false, "disable scheduler") 20 | dpdkLogLevel := flag.String("dpdk", "--log-level=0", "Passes an arbitrary argument to dpdk EAL") 21 | cores := flag.String("cores", "0-43", "Cores mask. Avoid hyperthreading here") 22 | flag.Parse() 23 | 24 | // Initialize NFF-GO library 25 | config := flow.Config{ 26 | DisableScheduler: *noscheduler, 27 | DPDKArgs: []string{*dpdkLogLevel}, 28 | CPUList: *cores, 29 | NoPacketHeadChange: true, 30 | } 31 | flow.CheckFatal(flow.SystemInit(&config)) 32 | 33 | // Receive packets from zero port. One queue per receive will be added automatically. 34 | firstFlow, err := flow.SetReceiver(uint16(*inport)) 35 | flow.CheckFatal(err) 36 | 37 | // Handle second flow via some heavy function 38 | if mode == 0 { 39 | flow.CheckFatal(flow.SetHandler(firstFlow, heavyFunc0, nil)) 40 | } else if mode == 1 { 41 | flow.CheckFatal(flow.SetHandler(firstFlow, heavyFunc1, nil)) 42 | } else { 43 | flow.CheckFatal(flow.SetHandler(firstFlow, heavyFunc2, nil)) 44 | } 45 | 46 | flow.CheckFatal(flow.SetSender(firstFlow, uint16(*outport))) 47 | 48 | flow.CheckFatal(flow.SystemStart()) 49 | } 50 | 51 | func heavyFunc0(currentPacket *packet.Packet, context flow.UserContext) { 52 | } 53 | 54 | func heavyFunc1(currentPacket *packet.Packet, context flow.UserContext) { 55 | currentPacket.ParseL3() 56 | } 57 | 58 | func heavyFunc2(currentPacket *packet.Packet, context flow.UserContext) { 59 | currentPacket.ParseL3() 60 | ipv4 := currentPacket.GetIPv4() 61 | if ipv4 != nil { 62 | T := ipv4.DstAddr 63 | ipv4.SrcAddr = 263 + (T) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/performance/perf_main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | "github.com/intel-go/nff-go/types" 13 | ) 14 | 15 | var ( 16 | load uint 17 | loadRW uint 18 | ) 19 | 20 | func main() { 21 | flag.UintVar(&load, "load", 1000, "Use this for regulating 'load intensity', number of iterations") 22 | flag.UintVar(&loadRW, "loadRW", 50, "Use this for regulating 'load read/write intensity', number of iterations") 23 | 24 | outport := flag.Uint("outport", 1, "port for sender") 25 | inport := flag.Uint("inport", 0, "port for receiver") 26 | noscheduler := flag.Bool("no-scheduler", false, "disable scheduler") 27 | dpdkLogLevel := flag.String("dpdk", "--log-level=0", "Passes an arbitrary argument to dpdk EAL") 28 | cores := flag.String("cores", "0-43", "Cores mask. Avoid hyperthreading here") 29 | flag.Parse() 30 | 31 | // Initialize NFF-GO library 32 | config := flow.Config{ 33 | DisableScheduler: *noscheduler, 34 | DPDKArgs: []string{*dpdkLogLevel}, 35 | CPUList: *cores, 36 | NoPacketHeadChange: true, 37 | } 38 | flow.CheckFatal(flow.SystemInit(&config)) 39 | 40 | // Receive packets from zero port. One queue per receive will be added automatically. 41 | firstFlow, err := flow.SetReceiver(uint16(*inport)) 42 | flow.CheckFatal(err) 43 | 44 | // Handle second flow via some heavy function 45 | flow.CheckFatal(flow.SetHandler(firstFlow, heavyFunc, nil)) 46 | 47 | flow.CheckFatal(flow.SetSender(firstFlow, uint16(*outport))) 48 | 49 | flow.CheckFatal(flow.SystemStart()) 50 | } 51 | 52 | func heavyFunc(currentPacket *packet.Packet, context flow.UserContext) { 53 | currentPacket.ParseL3() 54 | ipv4 := currentPacket.GetIPv4() 55 | if ipv4 != nil { 56 | T := ipv4.DstAddr 57 | for j := types.IPv4Address(0); j < types.IPv4Address(load); j++ { 58 | T += j 59 | } 60 | for i := types.IPv4Address(0); i < types.IPv4Address(loadRW); i++ { 61 | ipv4.DstAddr = ipv4.SrcAddr + i 62 | } 63 | ipv4.SrcAddr = 263 + (T) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/performance/perf_seq.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | "github.com/intel-go/nff-go/types" 13 | ) 14 | 15 | var ( 16 | load uint 17 | ) 18 | 19 | func main() { 20 | var err error 21 | var mode uint 22 | flag.UintVar(&load, "load", 1000, "Use this for regulating 'load intensity', number of iterations") 23 | flag.UintVar(&mode, "mode", 2, "Benching mode: 2, 12 - two handles; 3, 13 - tree handles; 4, 14 - four handles. 2,3,4 - one flow; 12,13,14 - two flows") 24 | outport := flag.Uint("outport", 1, "port for sender") 25 | inport := flag.Uint("inport", 0, "port for receiver") 26 | noscheduler := flag.Bool("no-scheduler", false, "disable scheduler") 27 | dpdkLogLevel := flag.String("dpdk", "--log-level=0", "Passes an arbitrary argument to dpdk EAL") 28 | cores := flag.String("cores", "0-43", "Cores mask. Avoid hyperthreading here") 29 | flag.Parse() 30 | 31 | // Initialize NFF-GO library 32 | config := flow.Config{ 33 | DisableScheduler: *noscheduler, 34 | DPDKArgs: []string{*dpdkLogLevel}, 35 | CPUList: *cores, 36 | NoPacketHeadChange: true, 37 | } 38 | flow.CheckFatal(flow.SystemInit(&config)) 39 | 40 | var tempFlow *flow.Flow 41 | var afterFlow *flow.Flow 42 | 43 | // Receive packets from zero port. One queue will be added automatically. 44 | firstFlow, err := flow.SetReceiver(uint16(*inport)) 45 | flow.CheckFatal(err) 46 | 47 | if mode > 10 { 48 | tempFlow, err = flow.SetPartitioner(firstFlow, 150, 150) 49 | flow.CheckFatal(err) 50 | } 51 | 52 | // Handle second flow via some heavy function 53 | flow.CheckFatal(flow.SetHandler(firstFlow, heavyFunc, nil)) 54 | flow.CheckFatal(flow.SetHandler(firstFlow, heavyFunc, nil)) 55 | if mode%10 > 2 { 56 | flow.CheckFatal(flow.SetHandler(firstFlow, heavyFunc, nil)) 57 | } 58 | if mode%10 > 3 { 59 | flow.CheckFatal(flow.SetHandler(firstFlow, heavyFunc, nil)) 60 | } 61 | if mode > 10 { 62 | flow.CheckFatal(flow.SetHandler(tempFlow, heavyFunc, nil)) 63 | flow.CheckFatal(flow.SetHandler(tempFlow, heavyFunc, nil)) 64 | if mode%10 > 2 { 65 | flow.CheckFatal(flow.SetHandler(tempFlow, heavyFunc, nil)) 66 | } 67 | if mode%10 > 3 { 68 | flow.CheckFatal(flow.SetHandler(tempFlow, heavyFunc, nil)) 69 | } 70 | afterFlow, err = flow.SetMerger(firstFlow, tempFlow) 71 | flow.CheckFatal(err) 72 | } else { 73 | afterFlow = firstFlow 74 | } 75 | 76 | flow.CheckFatal(flow.SetSender(afterFlow, uint16(*outport))) 77 | 78 | flow.CheckFatal(flow.SystemStart()) 79 | } 80 | 81 | func heavyFunc(currentPacket *packet.Packet, context flow.UserContext) { 82 | currentPacket.ParseL3() 83 | ipv4 := currentPacket.GetIPv4() 84 | if ipv4 != nil { 85 | T := (ipv4.DstAddr) 86 | for j := uint(0); j < load; j++ { 87 | T += types.IPv4Address(j) 88 | } 89 | ipv4.SrcAddr = 263 + (T) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/stability/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | SUBDIRS = testMerge testSingleWorkingFF testCksum 7 | 8 | include $(PATH_TO_MK)/intermediate.mk 9 | 10 | testing: 11 | for dir in $(SUBDIRS); do \ 12 | cd $$dir && make testing; cd -; \ 13 | done 14 | -------------------------------------------------------------------------------- /test/stability/testCksum/.gitignore: -------------------------------------------------------------------------------- 1 | testCksum 2 | config.json 3 | -------------------------------------------------------------------------------- /test/stability/testCksum/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY testCksum . 12 | -------------------------------------------------------------------------------- /test/stability/testCksum/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = nff-go-test-cksum 7 | EXECUTABLES = testCksum 8 | 9 | .PHONY: testing 10 | testing: check-pktgen 11 | go test -v -tags "${GO_BUILD_TAGS}" -test.timeout 15m 12 | 13 | include $(PATH_TO_MK)/leaf.mk 14 | -------------------------------------------------------------------------------- /test/stability/testCksum/checksum_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "log" 9 | "testing" 10 | ) 11 | 12 | func init() { 13 | if err := initTest(); err != nil { 14 | log.Fatalf("fail to initialize with error: %+v\n", err) 15 | } 16 | } 17 | 18 | // If it will fail due to strange mempool behaviour feel free to reopen https://github.com/intel-go/nff-go/issues/301 19 | func TestChecksum(t *testing.T) { 20 | variants := []struct{ useUDP, useTCP, useICMP bool }{ 21 | {false, false, false}, 22 | {true, false, false}, 23 | {false, true, false}, 24 | {false, false, true}, 25 | {true, true, false}} 26 | for _, useIPv4 := range []bool{true, false} { 27 | for _, useIPv6 := range []bool{true, false} { 28 | for _, useVLAN := range []bool{true, false} { 29 | for _, v := range variants { 30 | err := executeTest(gotest, useIPv4, useIPv6, v.useUDP, v.useTCP, v.useICMP, useVLAN) 31 | resetState() 32 | if err != nil { 33 | t.Logf("useIPv4=%t, useIPv6=%t, useUDP=%t, useTCP=%t, useICMP=%t, useVLAN=%t configuration failed with: %+v\n", useIPv4, useIPv6, v.useUDP, v.useTCP, v.useICMP, useVLAN, err) 34 | t.Fail() 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/stability/testMerge/.gitignore: -------------------------------------------------------------------------------- 1 | testMerge 2 | config.json 3 | -------------------------------------------------------------------------------- /test/stability/testMerge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY testMerge . 12 | COPY config.json . 13 | -------------------------------------------------------------------------------- /test/stability/testMerge/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = nff-go-test-merge 7 | EXECUTABLES = testMerge 8 | 9 | all: 10 | cp ../../framework/main/config.json . 11 | 12 | .PHONY: testing 13 | testing: check-pktgen 14 | go test -v -tags "${GO_BUILD_TAGS}" -test.timeout 20m 15 | 16 | include $(PATH_TO_MK)/leaf.mk 17 | -------------------------------------------------------------------------------- /test/stability/testMerge/merge_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "log" 9 | "testing" 10 | ) 11 | 12 | func init() { 13 | if err := initDPDK(); err != nil { 14 | log.Fatalf("fail to initialize with error: %+v\n", err) 15 | } 16 | } 17 | 18 | // If it will fail due to strange mempool behaviour feel free to reopen https://github.com/intel-go/nff-go/issues/301 19 | func TestMerge(t *testing.T) { 20 | scenarios := []pipelineScenario{getGet, segmGet, multipleSegm, singleSegm, getCopy, copyCopy, segmCopy} 21 | addSegmVariants := []bool{true, false} 22 | for _, scenario := range scenarios { 23 | for _, addSegm := range addSegmVariants { 24 | t.Logf("scenario: %d, add segment after merge: %t", scenario, addSegm) 25 | err := executeTest("", "", gotest, scenario, addSegm) 26 | resetState() 27 | if err != nil { 28 | t.Logf("fail: %v\n", err) 29 | t.Fail() 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/stability/testSingleWorkingFF/.gitignore: -------------------------------------------------------------------------------- 1 | config.json 2 | testSingleWorkingFF 3 | -------------------------------------------------------------------------------- /test/stability/testSingleWorkingFF/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY testSingleWorkingFF . 12 | COPY test-separate-l3rules.conf . 13 | COPY test-split.conf . 14 | COPY test-handle-l3rules.conf . 15 | COPY config.json . 16 | -------------------------------------------------------------------------------- /test/stability/testSingleWorkingFF/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../../mk 6 | IMAGENAME = nff-go-test-singleworkingff 7 | EXECUTABLES = testSingleWorkingFF 8 | 9 | all: 10 | cp ../../framework/main/config.json . 11 | 12 | .PHONY: testing 13 | testing: check-pktgen 14 | go test -v -tags "${GO_BUILD_TAGS}" 15 | 16 | include $(PATH_TO_MK)/leaf.mk 17 | -------------------------------------------------------------------------------- /test/stability/testSingleWorkingFF/singleWorkingFF_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "log" 9 | "testing" 10 | ) 11 | 12 | func init() { 13 | if err := initDPDK(); err != nil { 14 | log.Fatalf("fail: %+v\n", err) 15 | } 16 | } 17 | 18 | func TestSeparate(t *testing.T) { 19 | launch(t, separate) 20 | } 21 | 22 | func TestSplit(t *testing.T) { 23 | launch(t, split) 24 | } 25 | 26 | func TestPartition(t *testing.T) { 27 | launch(t, partition) 28 | } 29 | 30 | func TestCopy(t *testing.T) { 31 | launch(t, pcopy) 32 | } 33 | 34 | func TestHandle(t *testing.T) { 35 | launch(t, handle) 36 | } 37 | 38 | func TestHandleDrop(t *testing.T) { 39 | launch(t, dhandle) 40 | } 41 | 42 | func TestVectorSeparate(t *testing.T) { 43 | launch(t, vseparate) 44 | } 45 | 46 | func TestVectorSplit(t *testing.T) { 47 | launch(t, vsplit) 48 | } 49 | 50 | func TestVectorPartition(t *testing.T) { 51 | launch(t, vpartition) 52 | } 53 | 54 | func TestVectorHandle(t *testing.T) { 55 | launch(t, vhandle) 56 | } 57 | 58 | func TestVectorHandleDrop(t *testing.T) { 59 | launch(t, vdhandle) 60 | } 61 | 62 | func launch(t *testing.T, testType uint) { 63 | if err := executeTest("", "", gotest, testType); err != nil { 64 | t.Logf("fail: %+v\n", err) 65 | t.Fail() 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/stability/testSingleWorkingFF/test-handle-l3rules.conf: -------------------------------------------------------------------------------- 1 | # This file divides packets to three flows 2 | 3 | # Source address, Destination address, L4 protocol ID, Source port, Destination port, Output port 4 | ANY ANY ANY ANY 111 Accept 5 | ANY ANY ANY ANY 222 Reject 6 | -------------------------------------------------------------------------------- /test/stability/testSingleWorkingFF/test-separate-l3rules.conf: -------------------------------------------------------------------------------- 1 | # This file divides packets to three flows 2 | 3 | # Source address, Destination address, L4 protocol ID, Source port, Destination port, Output port 4 | ANY ANY ANY ANY 111 Accept 5 | ANY ANY ANY ANY 222 Reject 6 | -------------------------------------------------------------------------------- /test/stability/testSingleWorkingFF/test-split.conf: -------------------------------------------------------------------------------- 1 | # This file divides packets to three flows 2 | 3 | # Source address, Destination address, L4 protocol ID, Source port, Destination port, Output port 4 | ANY ANY ANY ANY 111 1 5 | ANY ANY ANY ANY 222 2 6 | ANY ANY ANY ANY 333 3 7 | -------------------------------------------------------------------------------- /test/stash/.gitignore: -------------------------------------------------------------------------------- 1 | forwardingTestL3 2 | sendback 3 | linuxReorderTestReceive 4 | linuxReorderTestSend 5 | -------------------------------------------------------------------------------- /test/stash/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | ARG USER_NAME 6 | FROM ${USER_NAME}/nff-go-base 7 | 8 | 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 9 | 10 | WORKDIR /workdir 11 | COPY forwardingTestL3 . 12 | COPY forwardingTestL3_ACL.conf . 13 | COPY forwardingTestL3_ACL.json . 14 | COPY sendback . 15 | COPY sendback.json . 16 | COPY linuxReorderTestReceive.go . 17 | COPY linuxReorderTestSend.go . 18 | -------------------------------------------------------------------------------- /test/stash/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../../mk 6 | IMAGENAME = nff-go-stash 7 | EXECUTABLES = forwardingTestL3 sendback linuxReorderTestReceive linuxReorderTestSend 8 | 9 | include $(PATH_TO_MK)/leaf.mk 10 | -------------------------------------------------------------------------------- /test/stash/forwardingTestL3.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | "github.com/intel-go/nff-go/packet" 12 | ) 13 | 14 | // L3ACL.json assumes that pktgen is configured the following way 15 | //Pktgen> src.ip min 0/1 111.2.0.0 16 | //Pktgen> src.ip max 0/1 111.2.0.4 17 | //Pktgen> src.ip inc 0/1 0.0.0.1 18 | //Pktgen> range.proto 0 udp 19 | //Pktgen> range.proto 1 tcp 20 | //Pktgen> src.port min 0/1 0 21 | //Pktgen> src.port max 0/1 29 22 | //Pktgen> src.port inc 0/1 1 23 | // We need two ports because pktgen can't generate tcp and udp both at one port. So we need to merge them. 24 | // Expected output (to achieve 60GB pktgen should be configured as above + packets per 256B each) 25 | // 0 - 7/30 (if input speed 60GB -> 14GB), always the same as "2" 26 | // 1 - 50% (if input speed 60GB -> 30GB) 27 | // 2 - 7/30 (if input speed 60GB -> 14GB), always the same as "0" 28 | // 3 - 1/30 (if input speed 60GB -> 2GB) 29 | // Pktgen MBits: 13743/30462 28634/29442 13743/0 1955/0 58076/59905 30 | 31 | var l3Rules *packet.L3Rules 32 | 33 | func main() { 34 | var err error 35 | mode := flag.String("mode", "orig", "Format of rules file") 36 | flag.Parse() 37 | 38 | // Initialize NFF-GO library at 16 available cores 39 | config := flow.Config{ 40 | CPUList: "0-15", 41 | } 42 | flow.CheckFatal(flow.SystemInit(&config)) 43 | 44 | // Start regular updating forwarding rules 45 | switch *mode { 46 | case "json": 47 | l3Rules, err = packet.GetL3ACLFromJSON("forwardingTestL3_ACL.json") 48 | flow.CheckFatal(err) 49 | case "orig": 50 | l3Rules, err = packet.GetL3ACLFromTextTable("forwardingTestL3_ACL.orig") 51 | flow.CheckFatal(err) 52 | } 53 | 54 | // Receive packets from zero port. One queue will be added automatically. 55 | firstFlow0, err := flow.SetReceiver(0) 56 | flow.CheckFatal(err) 57 | firstFlow1, err := flow.SetReceiver(1) 58 | flow.CheckFatal(err) 59 | 60 | // Merge flows with TCP and UDP packets 61 | firstFlow, err := flow.SetMerger(firstFlow0, firstFlow1) 62 | flow.CheckFatal(err) 63 | 64 | // Split packet flow based on ACL 65 | Flows, err := flow.SetSplitter(firstFlow, l3Splitter, 4, nil) 66 | flow.CheckFatal(err) 67 | 68 | // Send each flow to corresponding port 69 | // It is test. So we don't stop "0" packets, we count them as others. 70 | flow.CheckFatal(flow.SetSender(Flows[0], 0)) 71 | flow.CheckFatal(flow.SetSender(Flows[1], 1)) 72 | flow.CheckFatal(flow.SetSender(Flows[2], 2)) 73 | flow.CheckFatal(flow.SetSender(Flows[3], 3)) 74 | 75 | flow.CheckFatal(flow.SystemStart()) 76 | } 77 | 78 | func l3Splitter(currentPacket *packet.Packet, context flow.UserContext) uint { 79 | return currentPacket.L3ACLPort(l3Rules) 80 | } 81 | -------------------------------------------------------------------------------- /test/stash/forwardingTestL3_ACL.conf: -------------------------------------------------------------------------------- 1 | # While changing this file, please, make corresponding changes in forwardingTestL3_ACL.json file 2 | 3 | # Source address, Destination address, L4 protocol ID, Source port, Destination port, Output port 4 | 111.2.0.0/31 ANY tcp ANY ANY 2 5 | 111.2.0.2/32 ANY tcp ANY ANY Reject 6 | 111.2.0.4/32 ANY tcp 10:19 ANY 2 7 | 111.2.0.4/32 ANY tcp 20:29 ANY 3 8 | ANY ANY udp ANY ANY 1 9 | 10 | # TODO: Need to add empty port as 6 parameter, after its supporting in JSON 11 | -------------------------------------------------------------------------------- /test/stash/forwardingTestL3_ACL.json: -------------------------------------------------------------------------------- 1 | { 2 | "L3Rules": [ 3 | { 4 | "SrcAddr": "111.2.0.0/31", 5 | "DstAddr": "ANY", 6 | "ID": "tcp", 7 | "SrcPort": "ANY", 8 | "DstPort": "ANY", 9 | "OutputNumber": "2" 10 | }, 11 | { 12 | "SrcAddr": "111.2.0.2/32", 13 | "DstAddr": "ANY", 14 | "ID": "tcp", 15 | "SrcPort": "ANY", 16 | "DstPort": "ANY", 17 | "OutputNumber": "Reject" 18 | }, 19 | { 20 | "SrcAddr": "111.2.0.4/32", 21 | "DstAddr": "ANY", 22 | "ID": "tcp", 23 | "SrcPort": "10:19", 24 | "DstPort": "ANY", 25 | "OutputNumber": "2" 26 | }, 27 | { 28 | "SrcAddr": "111.2.0.4/32", 29 | "DstAddr": "ANY", 30 | "ID": "tcp", 31 | "SrcPort": "20:29", 32 | "DstPort": "ANY", 33 | "OutputNumber": "3" 34 | }, 35 | { 36 | "SrcAddr": "ANY", 37 | "DstAddr": "ANY", 38 | "ID": "udp", 39 | "SrcPort": "ANY", 40 | "DstPort": "ANY", 41 | "OutputNumber": "1" 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /test/stash/linuxReorderTestSend.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "encoding/binary" 8 | import "flag" 9 | import "log" 10 | import "net" 11 | import "strconv" 12 | import "sync" 13 | 14 | const ( 15 | network = "udp" 16 | ) 17 | 18 | func main() { 19 | target := flag.String("t", "", "Target host to send packets to.") 20 | port := flag.Uint("p", 33333, "First queue UDP port to send traffic to. Other queues use subsequent port numbers.") 21 | size := flag.Uint("s", 8, "Datagram packet size.") 22 | num := flag.Uint64("n", 10000, "Number of packets to send.") 23 | queues := flag.Uint("q", 1, "Number of simultaneous queues.") 24 | flag.Parse() 25 | 26 | if *size < uint(8) { 27 | log.Fatal("Packet size should not be less than 8 bytes.") 28 | } 29 | 30 | var wg sync.WaitGroup 31 | for q := uint(0); q < *queues; q++ { 32 | wg.Add(1) 33 | go send(&wg, *target, *port+q, *size, *num) 34 | } 35 | wg.Wait() 36 | } 37 | 38 | func send(wg *sync.WaitGroup, target string, port, size uint, num uint64) { 39 | defer wg.Done() 40 | addr, err := net.ResolveUDPAddr(network, target+":"+strconv.Itoa(int(port))) 41 | if err != nil { 42 | log.Fatal("ResolveUDPAddr returned ", err) 43 | } 44 | 45 | conn, err := net.DialUDP(network, nil, addr) 46 | if err != nil { 47 | log.Fatal("DialUDP returned ", err) 48 | } 49 | defer conn.Close() 50 | 51 | buffer := make([]byte, size) 52 | for i := uint64(1); i <= num; i++ { 53 | binary.BigEndian.PutUint64(buffer, uint64(i)) 54 | n, err := conn.Write(buffer) 55 | if err != nil { 56 | log.Fatal("Write returned ", err) 57 | } 58 | if uint(n) != size { 59 | log.Fatal("Failed to send a complete packet of size ", strconv.Itoa(int(size)), 60 | ", sent ", strconv.Itoa(n), " bytes instead") 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /test/stash/sendback.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | 10 | "github.com/intel-go/nff-go/flow" 11 | ) 12 | 13 | // This is a test for pure send/receive performance measurements. No 14 | // other functions used here. 15 | func main() { 16 | inport := flag.Uint("inport", 0, "Input port number") 17 | outport := flag.Uint("outport", 0, "Output port number") 18 | cores := flag.String("cores", "", "Specifies CPU cores to be used by NFF-GO library") 19 | dpdkLogLevel := flag.String("dpdk", "--log-level=0", "Passes an arbitrary argument to dpdk EAL") 20 | flag.Parse() 21 | 22 | // Initialize NFF-GO library 23 | config := flow.Config{ 24 | CPUList: *cores, 25 | DPDKArgs: []string{*dpdkLogLevel}, 26 | } 27 | flow.CheckFatal(flow.SystemInit(&config)) 28 | 29 | // Receive packets from input port. One queue will be added automatically. 30 | f, err := flow.SetReceiver(uint16(*inport)) 31 | flow.CheckFatal(err) 32 | 33 | flow.CheckFatal(flow.SetSender(f, uint16(*outport))) 34 | 35 | flow.CheckFatal(flow.SystemStart()) 36 | } 37 | -------------------------------------------------------------------------------- /types/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Intel Corporation. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PATH_TO_MK = ../mk 6 | include $(PATH_TO_MK)/include.mk 7 | 8 | .PHONY: testing 9 | testing: check-pktgen 10 | go test 11 | 12 | .PHONY: coverage 13 | coverage: 14 | go test -cover -coverprofile=c.out 15 | go tool cover -html=c.out -o common_coverage.html 16 | -------------------------------------------------------------------------------- /types/const.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types 6 | 7 | import ( 8 | "math" 9 | ) 10 | 11 | // Max array length for type conversions 12 | const MaxLength = math.MaxInt32 13 | 14 | // Length of addresses. 15 | const ( 16 | EtherAddrLen = 6 17 | IPv4AddrLen = 4 18 | IPv6AddrLen = 16 19 | ) 20 | 21 | // Supported EtherType for L2 22 | const ( 23 | IPV4Number = 0x0800 24 | ARPNumber = 0x0806 25 | VLANNumber = 0x8100 26 | MPLSNumber = 0x8847 27 | IPV6Number = 0x86dd 28 | 29 | SwapIPV4Number = 0x0008 30 | SwapARPNumber = 0x0608 31 | SwapVLANNumber = 0x0081 32 | SwapMPLSNumber = 0x4788 33 | SwapIPV6Number = 0xdd86 34 | ) 35 | 36 | // Supported L4 types 37 | const ( 38 | ICMPNumber = 0x01 39 | IPNumber = 0x04 40 | TCPNumber = 0x06 41 | UDPNumber = 0x11 42 | GRENumber = 0x2f 43 | ICMPv6Number = 0x3a 44 | NoNextHeader = 0x3b 45 | ) 46 | 47 | // Supported ICMP Types 48 | const ( 49 | ICMPTypeEchoRequest uint8 = 8 50 | ICMPTypeEchoResponse uint8 = 0 51 | ICMPv6TypeEchoRequest uint8 = 128 52 | ICMPv6TypeEchoResponse uint8 = 129 53 | ICMPv6NeighborSolicitation uint8 = 135 54 | ICMPv6NeighborAdvertisement uint8 = 136 55 | ) 56 | 57 | // These constants keep length of supported headers in bytes. 58 | // 59 | // IPv6Len - minimum length of IPv6 header in bytes. It can be higher and it 60 | // is not determined inside packet. Only default minimum size is used. 61 | // 62 | // IPv4MinLen and TCPMinLen are used only in packet generation functions. 63 | // 64 | // In parsing we take actual length of TCP header from DataOff field and length of 65 | // IPv4 take from Ihl field. 66 | const ( 67 | EtherLen = 14 68 | VLANLen = 4 69 | MPLSLen = 4 70 | IPv4MinLen = 20 71 | IPv6Len = 40 72 | ICMPLen = 8 73 | TCPMinLen = 20 74 | UDPLen = 8 75 | ARPLen = 28 76 | GTPMinLen = 8 77 | GRELen = 4 78 | ) 79 | 80 | const ( 81 | TCPMinDataOffset = 0x50 // minimal tcp data offset 82 | IPv4VersionIhl = 0x45 // IPv4, IHL = 5 (min header len) 83 | IPv6VtcFlow = 0x60 // IPv6 version 84 | ) 85 | 86 | // TCPFlags contains set TCP flags. 87 | type TCPFlags uint8 88 | 89 | // Constants for valuues of TCP flags. 90 | const ( 91 | TCPFlagFin = 0x01 92 | TCPFlagSyn = 0x02 93 | TCPFlagRst = 0x04 94 | TCPFlagPsh = 0x08 95 | TCPFlagAck = 0x10 96 | TCPFlagUrg = 0x20 97 | TCPFlagEce = 0x40 98 | TCPFlagCwr = 0x80 99 | ) 100 | -------------------------------------------------------------------------------- /types/ipv4.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | "net" 11 | ) 12 | 13 | type IPv4Address uint32 14 | 15 | // BytesToIPv4 converts four element address to IPv4Address representation 16 | func BytesToIPv4(a byte, b byte, c byte, d byte) IPv4Address { 17 | return IPv4Address(d)<<24 | IPv4Address(c)<<16 | IPv4Address(b)<<8 | IPv4Address(a) 18 | } 19 | 20 | // ArrayToIPv4 converts four element array to IPv4Address representation 21 | func ArrayToIPv4(a [IPv4AddrLen]byte) IPv4Address { 22 | return IPv4Address(a[3])<<24 | IPv4Address(a[2])<<16 | IPv4Address(a[1])<<8 | IPv4Address(a[0]) 23 | } 24 | 25 | // SliceToIPv4 converts four element slice to IPv4Address representation 26 | func SliceToIPv4(s []byte) IPv4Address { 27 | return IPv4Address(s[3])<<24 | IPv4Address(s[2])<<16 | IPv4Address(s[1])<<8 | IPv4Address(s[0]) 28 | } 29 | 30 | // IPv4ToBytes converts four element address to IPv4Address representation 31 | func IPv4ToBytes(v IPv4Address) [IPv4AddrLen]byte { 32 | return [IPv4AddrLen]uint8{byte(v), byte(v >> 8), byte(v >> 16), byte(v >> 24)} 33 | } 34 | 35 | func (addr IPv4Address) String() string { 36 | return fmt.Sprintf("%d.%d.%d.%d", byte(addr), byte(addr>>8), byte(addr>>16), byte(addr>>24)) 37 | } 38 | 39 | func IPv4ArrayToString(addr [IPv4AddrLen]uint8) string { 40 | return fmt.Sprintf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]) 41 | } 42 | 43 | // UnmarshalJSON parses IPv4 address. 44 | func (out *IPv4Address) UnmarshalJSON(b []byte) error { 45 | var s string 46 | if err := json.Unmarshal(b, &s); err != nil { 47 | return err 48 | } 49 | 50 | if ip := net.ParseIP(s); ip != nil { 51 | ipv4 := ip.To4() 52 | if ipv4 == nil { 53 | return fmt.Errorf("Bad IPv4 address %s", s) 54 | } 55 | *out = BytesToIPv4(ipv4[0], ipv4[1], ipv4[2], ipv4[3]) 56 | return nil 57 | } 58 | return fmt.Errorf("Failed to parse address %s", s) 59 | } 60 | -------------------------------------------------------------------------------- /types/ipv6.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | "net" 11 | ) 12 | 13 | type IPv6Address [IPv6AddrLen]uint8 14 | 15 | func (addr IPv6Address) String() string { 16 | return fmt.Sprintf("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", 17 | addr[0], addr[1], addr[2], addr[3], 18 | addr[4], addr[5], addr[6], addr[7], 19 | addr[8], addr[9], addr[10], addr[11], 20 | addr[12], addr[13], addr[14], addr[15]) 21 | } 22 | 23 | // UnmarshalJSON parses IPv6 address. 24 | func (out *IPv6Address) UnmarshalJSON(b []byte) error { 25 | var s string 26 | if err := json.Unmarshal(b, &s); err != nil { 27 | return err 28 | } 29 | 30 | if ip := net.ParseIP(s); ip != nil { 31 | ipv6 := ip.To16() 32 | if ipv6 == nil { 33 | return fmt.Errorf("Bad IPv6 address %s", s) 34 | } 35 | copy((*out)[:], ipv6) 36 | return nil 37 | } 38 | return fmt.Errorf("Failed to parse address %s", s) 39 | } 40 | -------------------------------------------------------------------------------- /types/mac.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Intel Corporation. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | "net" 11 | ) 12 | 13 | type MACAddress [EtherAddrLen]uint8 14 | 15 | // MACToString return MAC address like string 16 | func (mac MACAddress) String() string { 17 | return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) 18 | } 19 | 20 | // StringToMACAddress parses a string which contains a MAC address. 21 | func StringToMACAddress(str string) (MACAddress, error) { 22 | hw, err := net.ParseMAC(str) 23 | if err != nil { 24 | return MACAddress{}, err 25 | } 26 | var out MACAddress 27 | copy(out[:], hw) 28 | return out, nil 29 | } 30 | 31 | // UnmarshalJSON parses JSON element which contains string which 32 | // contains MAC address. 33 | func (out *MACAddress) UnmarshalJSON(b []byte) error { 34 | var s string 35 | err := json.Unmarshal(b, &s) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | *out, err = StringToMACAddress(s) 41 | return err 42 | } 43 | -------------------------------------------------------------------------------- /vagrant/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .vagrant 3 | config.ssh 4 | -------------------------------------------------------------------------------- /vagrant/getports.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | if (( "$#" != 1 )) 4 | then 5 | echo Usage: \$\(./getports.sh \\) 6 | echo Script generates \$sc0, \$sc1, etc variables if specified port is 22, and generates 7 | echo \$da0, \$da1, etc if specified port is 2375. 8 | echo If specified port is 2375, script also generates NFF_GO_HOSTS variable. 9 | echo 10 | echo If VM_TOTAL_NUMBER is set, it is used as a number of VMs, otherwise 2 is used. 11 | echo If VM_NAME is set, it is used as a VM name prefix, otherwise default \"nff-go\" is used. 12 | exit 2 13 | fi 14 | 15 | port_number=$1 16 | 17 | if [ -z "${VM_NAME}" ] 18 | then 19 | vm_prefix=nff-go- 20 | else 21 | vm_prefix=${VM_NAME}- 22 | fi 23 | 24 | if [ -z "${VM_TOTAL_NUMBER}" ] 25 | then 26 | number=3 27 | else 28 | number=${VM_TOTAL_NUMBER} 29 | fi 30 | 31 | if [ "${port_number}" == 22 ] 32 | then 33 | pp="sc" 34 | vagrant ssh-config > $(pwd)/config.ssh 35 | for (( i=0; i<${number}; i++ )) 36 | do 37 | echo export ${pp}${i}=$(pwd)/config.ssh 38 | done 39 | elif [ "${port_number}" == 2375 ] 40 | then 41 | hosts="" 42 | np_hosts="" 43 | pp="da" 44 | status=$(vagrant status) 45 | for (( i=0; i<${number}; i++ )) 46 | do 47 | vm_name=${vm_prefix}${i} 48 | if echo "${status}" | grep ${vm_name} | grep -q libvirt 49 | then 50 | config=$(vagrant ssh-config ${vm_name}) 51 | address=$(echo "${config}" | grep HostName | cut -d " " -f 4) 52 | port=${port_number} 53 | elif echo "${status}" | grep ${vm_name} | grep -q virtualbox 54 | then 55 | address=localhost 56 | port=$(vagrant port --guest ${port_number} ${vm_name}) 57 | else 58 | echo Unknown provider for VM ${vm_name} 59 | break 60 | fi 61 | 62 | echo export ${pp}${i}=${address}:${port} 63 | if (( i==0 )) 64 | then 65 | hosts=${address}:${port} 66 | np_hosts=${address} 67 | else 68 | hosts=${hosts},${address}:${port} 69 | np_hosts=${np_hosts},${address} 70 | fi 71 | done 72 | else 73 | echo Unknown port specified ${port_number} 74 | exit 1 75 | fi 76 | 77 | if [ "${port_number}" == 2375 ] 78 | then 79 | echo export NFF_GO_HOSTS=${hosts} 80 | echo export no_proxy=${np_hosts} 81 | fi 82 | --------------------------------------------------------------------------------