Skip to content

Commit

Permalink
Use bpf2go in dumpframes example (#8)
Browse files Browse the repository at this point in the history
* fix build error

* add xdp program via bpf2go to dumpframes example that can filter on the ip protocol number

* support ipv6

* fix comment

* move h_proto declaration to single line

* fix indentation

* use bpf2go@v0.4.0

* use cillium/ebpf@v0.4.0
  • Loading branch information
crandles committed Mar 26, 2021
1 parent b5fa400 commit 2936ad5
Show file tree
Hide file tree
Showing 16 changed files with 3,894 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@

# Developer
.vscode

# ebpf binaries
*.o

11 changes: 10 additions & 1 deletion examples/dumpframes/dumpframes.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@ import (
"net"

"github.com/asavie/xdp"
"github.com/asavie/xdp/examples/dumpframes/ebpf"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)

func main() {
var linkName string
var queueID int
var protocol int64

log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)

flag.StringVar(&linkName, "linkname", "enp3s0", "The network link on which rebroadcast should run on.")
flag.IntVar(&queueID, "queueid", 0, "The ID of the Rx queue to which to attach to on the network link.")
flag.Int64Var(&protocol, "ip-proto", 0, "If greater than 0 and less than or equal to 255, limit xdp bpf_redirect_map to packets with the specified IP protocol number.")
flag.Parse()

interfaces, err := net.Interfaces()
Expand All @@ -51,8 +54,14 @@ func main() {
return
}

var program *xdp.Program

// Create a new XDP eBPF program and attach it to our chosen network link.
program, err := xdp.NewProgram(queueID + 1)
if protocol == 0 {
program, err = xdp.NewProgram(queueID + 1)
} else {
program, err = ebpf.NewIPProtoProgram(uint32(protocol), nil)
}
if err != nil {
fmt.Printf("error: failed to create xdp program: %v\n", err)
return
Expand Down
15 changes: 15 additions & 0 deletions examples/dumpframes/ebpf/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM centos:8

RUN dnf install -y make cmake gcc gdb clang llvm clang-devel llvm-devel autoconf libtool kernel-devel libbpf elfutils-libelf-devel elfutils-devel

RUN /bin/bash -c " \
curl -fsSL https://golang.org/dl/go1.16.2.linux-amd64.tar.gz -o /tmp/golang.tar.gz && \
tar -C /usr/local -xzf /tmp/golang.tar.gz"

ENV PATH=$PATH:/usr/local/go/bin:/root/go/bin/

RUN dnf -y install git

RUN go get github.com/cilium/ebpf/cmd/bpf2go@v0.4.0

ENTRYPOINT ["bash", "-c", "cd /target/examples/dumpframes/ebpf && go generate"]
5 changes: 5 additions & 0 deletions examples/dumpframes/ebpf/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
docker:
docker build -t ebpf-generate -f Dockerfile .

generate:
docker run -i -t -v $$(pwd)/../../../:/target ebpf-generate
7 changes: 7 additions & 0 deletions examples/dumpframes/ebpf/include/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
LINUX_INC ?= /usr/include
LIBBPF_INC ?= /usr/local/include

.PHONY: update
update:
rsync --existing --exclude "types.h" -av "$(LINUX_INC)/linux/" "$(CURDIR)/linux"
rsync --existing -av "$(LIBBPF_INC)/bpf/" "$(CURDIR)/bpf"
99 changes: 99 additions & 0 deletions examples/dumpframes/ebpf/include/bpf/bpf_endian.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __BPF_ENDIAN__
#define __BPF_ENDIAN__

/*
* Isolate byte #n and put it into byte #m, for __u##b type.
* E.g., moving byte #6 (nnnnnnnn) into byte #1 (mmmmmmmm) for __u64:
* 1) xxxxxxxx nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx
* 2) nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 00000000
* 3) 00000000 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn
* 4) 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 00000000
*/
#define ___bpf_mvb(x, b, n, m) ((__u##b)(x) << (b-(n+1)*8) >> (b-8) << (m*8))

#define ___bpf_swab16(x) ((__u16)( \
___bpf_mvb(x, 16, 0, 1) | \
___bpf_mvb(x, 16, 1, 0)))

#define ___bpf_swab32(x) ((__u32)( \
___bpf_mvb(x, 32, 0, 3) | \
___bpf_mvb(x, 32, 1, 2) | \
___bpf_mvb(x, 32, 2, 1) | \
___bpf_mvb(x, 32, 3, 0)))

#define ___bpf_swab64(x) ((__u64)( \
___bpf_mvb(x, 64, 0, 7) | \
___bpf_mvb(x, 64, 1, 6) | \
___bpf_mvb(x, 64, 2, 5) | \
___bpf_mvb(x, 64, 3, 4) | \
___bpf_mvb(x, 64, 4, 3) | \
___bpf_mvb(x, 64, 5, 2) | \
___bpf_mvb(x, 64, 6, 1) | \
___bpf_mvb(x, 64, 7, 0)))

/* LLVM's BPF target selects the endianness of the CPU
* it compiles on, or the user specifies (bpfel/bpfeb),
* respectively. The used __BYTE_ORDER__ is defined by
* the compiler, we cannot rely on __BYTE_ORDER from
* libc headers, since it doesn't reflect the actual
* requested byte order.
*
* Note, LLVM's BPF target has different __builtin_bswapX()
* semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
* in bpfel and bpfeb case, which means below, that we map
* to cpu_to_be16(). We could use it unconditionally in BPF
* case, but better not rely on it, so that this header here
* can be used from application and BPF program side, which
* use different targets.
*/
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define __bpf_ntohs(x) __builtin_bswap16(x)
# define __bpf_htons(x) __builtin_bswap16(x)
# define __bpf_constant_ntohs(x) ___bpf_swab16(x)
# define __bpf_constant_htons(x) ___bpf_swab16(x)
# define __bpf_ntohl(x) __builtin_bswap32(x)
# define __bpf_htonl(x) __builtin_bswap32(x)
# define __bpf_constant_ntohl(x) ___bpf_swab32(x)
# define __bpf_constant_htonl(x) ___bpf_swab32(x)
# define __bpf_be64_to_cpu(x) __builtin_bswap64(x)
# define __bpf_cpu_to_be64(x) __builtin_bswap64(x)
# define __bpf_constant_be64_to_cpu(x) ___bpf_swab64(x)
# define __bpf_constant_cpu_to_be64(x) ___bpf_swab64(x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define __bpf_ntohs(x) (x)
# define __bpf_htons(x) (x)
# define __bpf_constant_ntohs(x) (x)
# define __bpf_constant_htons(x) (x)
# define __bpf_ntohl(x) (x)
# define __bpf_htonl(x) (x)
# define __bpf_constant_ntohl(x) (x)
# define __bpf_constant_htonl(x) (x)
# define __bpf_be64_to_cpu(x) (x)
# define __bpf_cpu_to_be64(x) (x)
# define __bpf_constant_be64_to_cpu(x) (x)
# define __bpf_constant_cpu_to_be64(x) (x)
#else
# error "Fix your compiler's __BYTE_ORDER__?!"
#endif

#define bpf_htons(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_htons(x) : __bpf_htons(x))
#define bpf_ntohs(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_ntohs(x) : __bpf_ntohs(x))
#define bpf_htonl(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_htonl(x) : __bpf_htonl(x))
#define bpf_ntohl(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_ntohl(x) : __bpf_ntohl(x))
#define bpf_cpu_to_be64(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_cpu_to_be64(x) : __bpf_cpu_to_be64(x))
#define bpf_be64_to_cpu(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_be64_to_cpu(x) : __bpf_be64_to_cpu(x))

#endif /* __BPF_ENDIAN__ */

0 comments on commit 2936ad5

Please sign in to comment.