Skip to content

Instantly share code, notes, and snippets.

@guesslin
Last active December 25, 2018 08:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guesslin/76be1139e5e3b8d71e964e194c5d9322 to your computer and use it in GitHub Desktop.
Save guesslin/76be1139e5e3b8d71e964e194c5d9322 to your computer and use it in GitHub Desktop.
/*
how to build (based on docker image golang:1.10):
$ apt-get update -qq && \
apt-get install -y pkg-config libpcap-dev curl cmake patch git libnuma-dev linux-source-4.9 libzmq3-dev unzip clang llvm libelf-dev && \
apt-get install -y --no-install-recommends bsdtar
# Prepare kernel and compile/install netmap/dpdk
$ cd /usr/src && \
bsdtar xJf linux-source-4.9.tar.xz && \
cp /usr/src/linux-config-4.9/config.amd64_none_amd64.xz /usr/src/linux-source-4.9 && \
cd /usr/src/linux-source-4.9 && \
unxz config.amd64_none_amd64.xz && \
mv config.amd64_none_amd64 .config && \
make oldconfig && \
make modules_prepare
# stringer for nff-go
$ go get -u golang.org/x/tools/cmd/stringer
# fix for cgo ld flags
$ export CGO_LDFLAGS_ALLOW='(-export-dynamic|-Wl,(--whole-archive|--no-whole-archive|--as-needed|--cref))'
# clone nff-go to $GOPATH
$ cd /go/src && git clone -b v0.7.0 --single-branch --depth=1 https://github.com/intel-go/nff-go/
$ cd /go/src/github.com/intel-go/nff-go
$ then apt-get install -y lua5.3-dev
$ git submodule init && git submodule update
$ make RTE_KERNELDIR=/usr/src/linux-source-4.9 -C nff-go-base
$ make RTE_KERNELDIR=/usr/src/linux-source-4.9 -C dpdk
then replace CFLAGS and LD_FLAGS of cgo in /go/src/github.com/intel-go/nff-go/low/low.go
// #cgo CFLAGS: -I/go/src/github.com/intel-go/nff-go/dpdk/dpdk/x86_64-native-linuxapp-gcc/include -O3 -g -m64 -pthread -std=gnu11 -march=native -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3 -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_RDRAND -DRTE_MACHINE_CPUFLAG_F16C -Wno-deprecated-declarations
// #cgo LDFLAGS: -L/go/src/github.com/intel-go/nff-go/dpdk/dpdk/x86_64-native-linuxapp-gcc/lib -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
// #include "low.h"
then run `go build` to get the binary
*/
package main
import (
"flag"
"fmt"
"log"
"net"
"time"
"github.com/intel-go/nff-go/devices"
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/low"
libpacket "github.com/intel-go/nff-go/packet"
)
var (
nicName = flag.String("n", "eth1", "target network interface to run dpdk")
driver = flag.String("d", "igb_uio", "target driver to run dpdk")
)
func main() {
flag.Parse()
macAddr, err := net.InterfaceByName(*nicName)
panicOnError(err, "can't find mac address of target nic")
instance, err := New(*nicName, *driver, macAddr.HardwareAddr)
panicOnError(err, "start dpdk/nff-go failed")
defer instance.Close()
time.Sleep(10 * time.Second)
}
func panicOnError(err error, msg string) {
if err != nil {
panic(fmt.Sprintf("Erorr: %s, Msg: %s\n", err, msg))
}
}
type Nff struct {
port uint16
}
func New(nicName, targetDriver string, macAddr net.HardwareAddr) (*Nff, error) {
instance := &Nff{}
if err := instance.bindNicWithDriver(nicName, targetDriver); err != nil {
return nil, err
}
if err := instance.startFlow(macAddr); err != nil {
return nil, err
}
return instance, nil
}
func (n *Nff) bindNicWithDriver(nicName, targetDriver string) error {
// setup Binder for given nicName
device, err := devices.New(nicName)
if err != nil {
return err
}
log.Printf("Binding PMD driver %s to NIC %s\n", nicName, targetDriver)
// use devices.Device to bind target driver
return device.Bind(targetDriver)
}
func (n *Nff) startFlow(macAddr net.HardwareAddr) error {
log.Println("Initiating nff-go flow system")
config := &flow.Config{HWTXChecksum: true}
flow.SystemInit(config)
log.Println("Initiated nff-go flow system")
// NOTE: Must be called after flow.SystemInit
n.port = getEthPort(macAddr)
// Main flow from receiver (port 0)
log.Println("Setting receiver on port", n.port)
mainFlow, err := flow.SetReceiver(n.port)
if err != nil {
return err
}
log.Println("Set receiver on port", n.port)
log.Println("Setting drop handler on port", n.port)
// Packet handler: by-pass all packets
if err := flow.SetHandlerDrop(mainFlow, n.handler, nil); err != nil {
return err
}
log.Println("Set drop handler on port", n.port)
// Send packet back to port 0
log.Println("Setting sender on port", n.port)
if err := flow.SetSender(mainFlow, n.port); err != nil {
return err
}
log.Println("Set sender on port", n.port)
go func() {
log.Println("Starting flow system")
if err := flow.SystemStart(); err != nil {
log.Println("Couldn't start NFF system:", err.Error())
}
}()
return nil
}
func (n *Nff) handler(pkt *libpacket.Packet, _ flow.UserContext) bool {
// XXX: just bypass packets
return true
}
func (n *Nff) Close() {
// Stop nff-go system
log.Println("Stop NFF-Go SystemStop")
flow.SystemStop()
log.Println("Setup Systemd ExecStartPost config for DPDK PMD driver unregister")
}
func getEthPort(hwaddr net.HardwareAddr) uint16 {
for p := 0; p < low.GetPortsNumber(); p++ {
portMACAddress := low.GetPortMACAddress(uint16(p))
if hardwareAddressEqual(hwaddr, net.HardwareAddr(portMACAddress[:])) {
return uint16(p)
}
}
return 0
}
func hardwareAddressEqual(addr1, addr2 net.HardwareAddr) bool {
for i, j := 0, 0; i < len(addr1) && j < len(addr2); i, j = i+1, j+1 {
if addr1[i] != addr2[j] {
return false
}
}
return true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment