Last active
December 25, 2018 08:27
-
-
Save guesslin/76be1139e5e3b8d71e964e194c5d9322 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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