Skip to content

Commit ac3fc59

Browse files
authored
Merge pull request #656 from safchain/ebpf-fixes
flow: add conditional ebpf probe build
2 parents c2d50c6 + a930586 commit ac3fc59

File tree

10 files changed

+185
-94
lines changed

10 files changed

+185
-94
lines changed

.travis.yml

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ go:
55
- 1.9.1
66

77
sudo: required
8-
dist: trusty
8+
dist: xenial
99

1010
before_install:
1111
- sudo apt-get -qq update
12-
- sudo apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y openvswitch-switch unzip docker.io build-essential flex bison libxml2-dev libz-dev liblzma-dev libicu-dev libc++-dev bridge-utils libdb5.1-dev libgraph-easy-perl screen inotify-tools realpath libnuma-dev linux-headers-$(uname -r)
12+
- sudo apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y openvswitch-switch unzip docker.io build-essential flex bison libxml2-dev libz-dev liblzma-dev libicu-dev libc++-dev bridge-utils libdb5.3-dev libgraph-easy-perl screen inotify-tools realpath libnuma-dev linux-headers-$(uname -r)
1313
- sudo ovs-vsctl show
1414
- sudo iptables -F
1515
- for i in $(find /proc/sys/net/bridge/ -type f) ; do echo 0 | sudo tee $i ; done
@@ -24,13 +24,6 @@ before_install:
2424
- sudo make install
2525
- cd ..
2626

27-
- wget https://www.kernel.org/pub/linux/utils/net/iproute2/iproute2-4.0.0.tar.gz
28-
- tar -xvzf iproute2-4.0.0.tar.gz
29-
- cd iproute2-4.0.0
30-
- make
31-
- sudo make install
32-
- cd ..
33-
3427
- mkdir ${HOME}/protoc
3528
- pushd ${HOME}/protoc
3629
- wget https://github.com/google/protobuf/releases/download/v3.1.0/protoc-3.1.0-linux-x86_64.zip
@@ -42,7 +35,7 @@ script:
4235
- export BUILD_TAG=$(date +%Y-%m-%d).${TRAVIS_JOB_NUMBER}
4336
- export PATH=${GOPATH}/bin:${PATH}
4437

45-
- make WITH_DPDK=true install
38+
- make WITH_DPDK=true WITH_EBPF=true install
4639
- make static
4740

4841
- echo "--- DOCKER IMAGE ---"

Makefile

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ BOOTSTRAP_ARGS?=
3232
GOTAGS?=
3333

3434
ifeq ($(WITH_DPDK), true)
35-
GOTAGS+=dpdk
35+
BUILDTAGS+=dpdk
36+
endif
37+
38+
ifeq ($(WITH_EBPF), true)
39+
BUILDTAGS+=ebpf
40+
EXTRABINDATA+=probe/ebpf/*.o
3641
endif
3742

3843
.PHONY: all
@@ -50,21 +55,21 @@ all: install
5055
sed -e 's/type Flow struct {/type Flow struct {\n\tXXX_state flowState `json:"-"`/' -i flow/flow.pb.go
5156

5257
.bindata: builddep ebpf.build
53-
go-bindata ${GO_BINDATA_FLAGS} -nometadata -o statics/bindata.go -pkg=statics -ignore=bindata.go statics/* statics/css/images/* statics/js/vendor/* statics/js/components/* probe/ebpf/*.o
58+
go-bindata ${GO_BINDATA_FLAGS} -nometadata -o statics/bindata.go -pkg=statics -ignore=bindata.go statics/* statics/css/images/* statics/js/vendor/* statics/js/components/* ${EXTRABINDATA}
5459
gofmt -w -s statics/bindata.go
5560

5661
.compile:
57-
${GOPATH}/bin/govendor install -ldflags="-X github.com/skydive-project/skydive/version.Version=${VERSION}" ${GOFLAGS} -tags=" ${GOTAGS}" ${VERBOSE_FLAGS} +local
62+
${GOPATH}/bin/govendor install -ldflags="-X github.com/skydive-project/skydive/version.Version=${VERSION}" ${GOFLAGS} -tags="${BUILDTAGS} ${GOTAGS}" ${VERBOSE_FLAGS} +local
5863

5964
install: govendor genlocalfiles dpdk.build contribs .compile
6065

6166
build: govendor genlocalfiles dpdk.build contribs
62-
${GOPATH}/bin/govendor build -ldflags="-X github.com/skydive-project/skydive/version.Version=${VERSION}" ${GOFLAGS} -tags=" ${GOTAGS}" ${VERBOSE_FLAGS} +local
67+
${GOPATH}/bin/govendor build -ldflags="-X github.com/skydive-project/skydive/version.Version=${VERSION}" ${GOFLAGS} -tags="${BUILDTAGS} ${GOTAGS}" ${VERBOSE_FLAGS} +local
6368

6469
static: #govendor genlocalfiles
6570
rm -f $$GOPATH/bin/skydive
66-
test -f /etc/redhat-release && govendor install -tags netgo --ldflags '-extldflags "-static /usr/lib64/libz.a /usr/lib64/liblzma.a /usr/lib64/libm.a"' ${VERBOSE_FLAGS} -tags " ${GOTAGS}" +local || true
67-
test -f /etc/debian_version && govendor install -tags netgo --ldflags '-extldflags "-static /usr/lib/x86_64-linux-gnu/libz.a /usr/lib/x86_64-linux-gnu/liblzma.a /usr/lib/x86_64-linux-gnu/libicuuc.a /usr/lib/x86_64-linux-gnu/libicudata.a /usr/lib/x86_64-linux-gnu/libxml2.a /usr/lib/x86_64-linux-gnu/libc.a /usr/lib/x86_64-linux-gnu/libdl.a /usr/lib/x86_64-linux-gnu/libpthread.a /usr/lib/x86_64-linux-gnu/libc++.a /usr/lib/x86_64-linux-gnu/libm.a"' ${VERBOSE_FLAGS} -tags " ${GOTAGS}" +local || true
71+
test -f /etc/redhat-release && govendor install -tags netgo --ldflags '-extldflags "-static /usr/lib64/libz.a /usr/lib64/liblzma.a /usr/lib64/libm.a"' ${VERBOSE_FLAGS} -tags "${BUILDTAGS} ${GOTAGS}" +local || true
72+
test -f /etc/debian_version && govendor install -tags netgo --ldflags '-extldflags "-static /usr/lib/x86_64-linux-gnu/libz.a /usr/lib/x86_64-linux-gnu/liblzma.a /usr/lib/x86_64-linux-gnu/libicuuc.a /usr/lib/x86_64-linux-gnu/libicudata.a /usr/lib/x86_64-linux-gnu/libxml2.a /usr/lib/x86_64-linux-gnu/libc.a /usr/lib/x86_64-linux-gnu/libdl.a /usr/lib/x86_64-linux-gnu/libpthread.a /usr/lib/x86_64-linux-gnu/libc++.a /usr/lib/x86_64-linux-gnu/libm.a"' ${VERBOSE_FLAGS} -tags "${BUILDTAGS} ${GOTAGS}" +local || true
6873

6974
contribs:
7075
$(MAKE) -C contrib/snort
@@ -78,7 +83,9 @@ dpdk.cleanup:
7883
$(MAKE) -C dpdk clean
7984

8085
ebpf.build:
86+
ifeq ($(WITH_EBPF), true)
8187
$(MAKE) -C probe/ebpf
88+
endif
8289

8390
ebpf.clean:
8491
$(MAKE) -C probe/ebpf clean
@@ -87,7 +94,7 @@ test.functionals.cleanup:
8794
rm -f tests/functionals
8895

8996
test.functionals.compile: govendor genlocalfiles
90-
${GOPATH}/bin/govendor test -tags "${GOTAGS} test" ${GOFLAGS} ${VERBOSE_FLAGS} -timeout ${TIMEOUT} -c -o tests/functionals ./tests/
97+
${GOPATH}/bin/govendor test -tags "${BUILDTAGS} ${GOTAGS} test" ${GOFLAGS} ${VERBOSE_FLAGS} -timeout ${TIMEOUT} -c -o tests/functionals ./tests/
9198

9299
test.functionals.run:
93100
cd tests && sudo -E ./functionals ${VERBOSE_TESTS_FLAGS} -test.timeout ${TIMEOUT} ${ARGS}
@@ -117,12 +124,12 @@ ifeq ($(COVERAGE), true)
117124
for pkg in ${UT_PACKAGES}; do \
118125
if [ -n "$$pkg" ]; then \
119126
coverfile="${COVERAGE_WD}/$$(echo $$pkg | tr / -).cover"; \
120-
${GOPATH}/bin/govendor test -tags "${GOTAGS} test" -covermode=${COVERAGE_MODE} -coverprofile="$$coverfile" ${VERBOSE_FLAGS} -timeout ${TIMEOUT} $$pkg; \
127+
${GOPATH}/bin/govendor test -tags "${BUILDTAGS} ${GOTAGS} test" -covermode=${COVERAGE_MODE} -coverprofile="$$coverfile" ${VERBOSE_FLAGS} -timeout ${TIMEOUT} $$pkg; \
121128
fi; \
122129
done
123130
else
124131
set -v ; \
125-
${GOPATH}/bin/govendor test -tags "${GOTAGS} test" ${GOFLAGS} ${VERBOSE_FLAGS} -timeout ${TIMEOUT} ${UT_PACKAGES}
132+
${GOPATH}/bin/govendor test -tags "${BUILDTAGS} ${GOTAGS} test" ${GOFLAGS} ${VERBOSE_FLAGS} -timeout ${TIMEOUT} ${UT_PACKAGES}
126133
endif
127134

128135
govendor:

doc/content/getting-started/install.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Skydive relies on two main components:
2020
* protoc >= 3.0
2121
* llvm
2222
* clang
23-
* kernel-headers
23+
* kernel-headers / linux-libc-dev
2424

2525
## Install
2626

flow/probes/ebpf.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// +build ebpf
2+
13
/*
24
* Copyright (C) 2017 Red Hat, Inc.
35
*

flow/probes/no_ebpf.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// +build !ebpf
2+
3+
/*
4+
* Copyright (C) 2017 Red Hat, Inc.
5+
*
6+
* Licensed to the Apache Software Foundation (ASF) under one
7+
* or more contributor license agreements. See the NOTICE file
8+
* distributed with this work for additional information
9+
* regarding copyright ownership. The ASF licenses this file
10+
* to you under the Apache License, Version 2.0 (the
11+
* "License"); you may not use this file except in compliance
12+
* with the License. You may obtain a copy of the License at
13+
*
14+
* http://www.apache.org/licenses/LICENSE-2.0
15+
*
16+
* Unless required by applicable law or agreed to in writing,
17+
* software distributed under the License is distributed on an
18+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19+
* KIND, either express or implied. See the License for the
20+
* specific language governing permissions and limitations
21+
* under the License.
22+
*
23+
*/
24+
25+
package probes
26+
27+
import (
28+
"github.com/skydive-project/skydive/api"
29+
"github.com/skydive-project/skydive/topology/graph"
30+
)
31+
32+
// EBPFProbesHandler describes a flow probe handle in the graph
33+
type EBPFProbesHandler struct {
34+
}
35+
36+
// RegisterProbe registers a gopacket probe
37+
func (p *EBPFProbesHandler) RegisterProbe(n *graph.Node, capture *api.Capture, e FlowProbeEventHandler) error {
38+
return nil
39+
}
40+
41+
// UnregisterProbe unregisters gopacket probe
42+
func (p *EBPFProbesHandler) UnregisterProbe(n *graph.Node, e FlowProbeEventHandler) error {
43+
return nil
44+
}
45+
46+
// Start probe
47+
func (p *EBPFProbesHandler) Start() {
48+
}
49+
50+
// Stop probe
51+
func (p *EBPFProbesHandler) Stop() {
52+
}
53+
54+
// NewEBPFProbesHandler creates a new gopacket probe in the graph
55+
func NewEBPFProbesHandler(g *graph.Graph, fpta *FlowProbeTableAllocator) (*EBPFProbesHandler, error) {
56+
return nil, ErrProbeNotCompiled
57+
}

flow/probes/probes.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,23 +97,22 @@ func NewFlowProbeBundle(tb *probe.ProbeBundle, g *graph.Graph, fta *flow.TableAl
9797
fp, err = NewSFlowProbesHandler(g, fpta)
9898
captureTypes = []string{"sflow"}
9999
case "dpdk":
100-
fp, err = NewDPDKProbesHandler(g, fpta)
101-
if err == ErrProbeNotCompiled {
102-
logging.GetLogger().Info("Not compiled with DPDK support, skipping it")
103-
continue
104-
} else if err == nil {
100+
if fp, err = NewDPDKProbesHandler(g, fpta); err == nil {
105101
captureTypes = []string{"dpdk"}
106102
}
107103
case "ebpf":
108-
fp, err = NewEBPFProbesHandler(g, fpta)
109-
captureTypes = []string{"ebpf"}
104+
if fp, err = NewEBPFProbesHandler(g, fpta); err == nil {
105+
captureTypes = []string{"ebpf"}
106+
}
110107
default:
111108
err = fmt.Errorf("unknown probe type %s", t)
112109
}
113110

114111
if err != nil {
115112
if err != ErrProbeNotCompiled {
116-
logging.GetLogger().Errorf("failed to create %s probe: %s", t, err.Error())
113+
logging.GetLogger().Errorf("Failed to create %s probe: %s", t, err)
114+
} else {
115+
logging.GetLogger().Infof("Not compiled with %s support, skipping it", t)
117116
}
118117
continue
119118
}

probe/ebpf/flow.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,25 +56,25 @@ MAP(flow_table) {
5656
.max_entries = 500000,
5757
};
5858

59-
static __always_inline void update_hash_byte(__u64 *key, __u8 byte)
59+
static inline void update_hash_byte(__u64 *key, __u8 byte)
6060
{
6161
*key ^= (__u64)byte;
6262
*key *= FNV_PRIME;
6363
}
6464

65-
static __always_inline void update_hash_half(__u64 *key, __u16 half)
65+
static inline void update_hash_half(__u64 *key, __u16 half)
6666
{
6767
update_hash_byte(key, (half >> 8) & 0xff);
6868
update_hash_byte(key, half & 0xff);
6969
}
7070

71-
static __always_inline void update_hash_word(__u64 *key, __u32 word)
71+
static inline void update_hash_word(__u64 *key, __u32 word)
7272
{
7373
update_hash_half(key, (word >> 16) & 0xffff);
7474
update_hash_half(key, word & 0xffff);
7575
}
7676

77-
static __always_inline void fill_payload_bucket(struct __sk_buff *skb, int offset, __u8 *bucket, int bsize) {
77+
static inline void fill_payload_bucket(struct __sk_buff *skb, int offset, __u8 *bucket, int bsize) {
7878
for (int i = 0; i != bsize; i++) {
7979
bucket[i] = load_byte(skb, offset + i);
8080
}
@@ -83,7 +83,7 @@ static __always_inline void fill_payload_bucket(struct __sk_buff *skb, int offse
8383
static void fill_payload(struct __sk_buff *skb, int offset, struct flow *flow, int len)
8484
{
8585
// TODO add more data
86-
return fill_payload_bucket(skb, offset, flow->payload, 30);
86+
fill_payload_bucket(skb, offset, flow->payload, 30);
8787
}
8888

8989
static void fill_transport(struct __sk_buff *skb, __u8 protocol, int offset,
@@ -177,14 +177,14 @@ static void fill_word(__u32 src, __u8 *dst, int offset)
177177
dst[offset + 3] = src & 0xff;
178178
}
179179

180-
static __always_inline void fill_ipv4(struct __sk_buff *skb, int offset, __u8 *dst, __u64 *hash)
180+
static inline void fill_ipv4(struct __sk_buff *skb, int offset, __u8 *dst, __u64 *hash)
181181
{
182182
__u32 w = load_word(skb, offset);
183183
fill_word(w, dst, 12);
184184
update_hash_word(hash, w);
185185
}
186186

187-
static __always_inline void fill_ipv6(struct __sk_buff *skb, int offset, __u8 *dst, __u64 *hash)
187+
static inline void fill_ipv6(struct __sk_buff *skb, int offset, __u8 *dst, __u64 *hash)
188188
{
189189
__u32 w = load_word(skb, offset);
190190
fill_word(w, dst, 0);
@@ -266,7 +266,7 @@ static void fill_network(struct __sk_buff *skb, __u16 protocol, int offset,
266266
flow->layers |= NETWORK_LAYER;
267267
}
268268

269-
static __always_inline void fill_haddr(struct __sk_buff *skb, int offset,
269+
static inline void fill_haddr(struct __sk_buff *skb, int offset,
270270
unsigned char *mac)
271271
{
272272
mac[0] = load_byte(skb, offset);

scripts/ci/run-functional-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ case "$BACKEND" in
2525
esac
2626

2727
set -e
28-
make test.functionals.batch GOTAGS="$GOTAGS" GOFLAGS="$GOFLAGS" GORACE="history_size=5" VERBOSE=true TIMEOUT=20m COVERAGE=$COVERAGE ARGS="$ARGS -graph.output ascii -standalone -etcd.server http://localhost:2379" TEST_PATTERN=$TEST_PATTERN 2>&1 | tee $WORKSPACE/output.log
28+
make test.functionals.batch GOTAGS="$GOTAGS" GOFLAGS="$GOFLAGS" GORACE="history_size=5" WITH_EBPF=true VERBOSE=true TIMEOUT=20m COVERAGE=$COVERAGE ARGS="$ARGS -graph.output ascii -standalone -etcd.server http://localhost:2379" TEST_PATTERN=$TEST_PATTERN 2>&1 | tee $WORKSPACE/output.log
2929
go2xunit -fail -fail-on-race -input $WORKSPACE/output.log -output $WORKSPACE/tests.xml
3030
set +e
3131

tests/flow_ebpf_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// +build ebpf
2+
3+
/*
4+
* Copyright (C) 2016 Red Hat, Inc.
5+
*
6+
* Licensed to the Apache Software Foundation (ASF) under one
7+
* or more contributor license agreements. See the NOTICE file
8+
* distributed with this work for additional information
9+
* regarding copyright ownership. The ASF licenses this file
10+
* to you under the Apache License, Version 2.0 (the
11+
* "License"); you may not use this file except in compliance
12+
* with the License. You may obtain a copy of the License at
13+
*
14+
* http://www.apache.org/licenses/LICENSE-2.0
15+
*
16+
* Unless required by applicable law or agreed to in writing,
17+
* software distributed under the License is distributed on an
18+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19+
* KIND, either express or implied. See the License for the
20+
* specific language governing permissions and limitations
21+
* under the License.
22+
*
23+
*/
24+
25+
package tests
26+
27+
import (
28+
"fmt"
29+
"testing"
30+
31+
"github.com/skydive-project/skydive/common"
32+
"github.com/skydive-project/skydive/tests/helper"
33+
)
34+
35+
func TestFlowsEBPF(t *testing.T) {
36+
test := &Test{
37+
setupCmds: []helper.Cmd{
38+
{"ovs-vsctl add-br br-ebpf", true},
39+
40+
{"ip netns add src-vm", true},
41+
{"ip link add src-vm-eth0 type veth peer name ebpf-src-eth0 netns src-vm", true},
42+
{"ip link set src-vm-eth0 up", true},
43+
{"ip netns exec src-vm ip link set ebpf-src-eth0 up", true},
44+
{"ip netns exec src-vm ip address add 169.254.107.33/24 dev ebpf-src-eth0", true},
45+
46+
{"ip netns add dst-vm", true},
47+
{"ip link add dst-vm-eth0 type veth peer name ebpf-dst-eth0 netns dst-vm", true},
48+
{"ip link set dst-vm-eth0 up", true},
49+
{"ip netns exec dst-vm ip link set ebpf-dst-eth0 up", true},
50+
{"ip netns exec dst-vm ip address add 169.254.107.34/24 dev ebpf-dst-eth0", true},
51+
52+
{"ovs-vsctl add-port br-ebpf src-vm-eth0", true},
53+
{"ovs-vsctl add-port br-ebpf dst-vm-eth0", true},
54+
},
55+
56+
setupFunction: func(c *TestContext) (err error) {
57+
return ping(t, c, 4, "G.V().Has('Name', 'ebpf-src-eth0')", "G.V().Has('Name', 'ebpf-dst-eth0')", 10, 0)
58+
},
59+
60+
tearDownCmds: []helper.Cmd{
61+
{"ovs-vsctl del-br br-ebpf", true},
62+
{"ip link del dst-vm-eth0", true},
63+
{"ip link del src-vm-eth0", true},
64+
{"ip netns del src-vm", true},
65+
{"ip netns del dst-vm", true},
66+
},
67+
68+
captures: []TestCapture{
69+
{gremlin: `G.V().Has('Name', 'ebpf-src-eth0')`, kind: "ebpf"},
70+
},
71+
72+
checks: []CheckFunction{func(c *CheckContext) error {
73+
g := "g"
74+
if !c.time.IsZero() {
75+
g += fmt.Sprintf(".Context(%d)", common.UnixMillis(c.time))
76+
}
77+
gremlin := g + ".Flows().Has('Network', '169.254.107.33', 'LayersPath', 'Ethernet/IPv4/ICMPv4').Dedup()"
78+
flows, err := c.gh.GetFlows(gremlin)
79+
if err != nil {
80+
return err
81+
}
82+
if len(flows) != 1 || flows[0].Metric.ABPackets != 10 {
83+
return fmt.Errorf("Expected one flow, got %+v", flows)
84+
}
85+
86+
return nil
87+
}},
88+
}
89+
RunTest(t, test)
90+
}

0 commit comments

Comments
 (0)