diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e82f1059958b3b4c8b018a32a84436041e3b29a..88ce0212189dba3e296475a85152bbd1b4a80d96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,9 @@ find_library(libclangParse NAMES clangParse HINTS ${CLANG_SEARCH}) find_library(libclangRewrite NAMES clangRewrite HINTS ${CLANG_SEARCH}) find_library(libclangSema NAMES clangSema HINTS ${CLANG_SEARCH}) find_library(libclangSerialization NAMES clangSerialization HINTS ${CLANG_SEARCH}) +if(libclangBasic STREQUAL "libclangBasic-NOTFOUND") + message(FATAL_ERROR "Unable to find clang libraries") +endif() set(CMAKE_C_FLAGS "-Wall") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall") diff --git a/README.md b/README.md index 166b84de39a117c21be366458d2e611d5013f52a..05cf2ec034db94dc69379048e482d1b7c91ba84c 100644 --- a/README.md +++ b/README.md @@ -36,89 +36,69 @@ The features of this toolkit include: To get started using this toolchain, one needs: * Linux kernel 4.1 or newer, with these flags enabled: - * CONFIG_BPF=y - * CONFIG_BPF_SYSCALL=y - * CONFIG_NET_CLS_BPF=m [optional, for tc filters] - * CONFIG_NET_ACT_BPF=m [optional, for tc actions] - * CONFIG_BPF_JIT=y - * CONFIG_HAVE_BPF_JIT=y - * CONFIG_BPF_EVENTS=y [optional, for kprobes] + * `CONFIG_BPF=y` + * `CONFIG_BPF_SYSCALL=y` + * `CONFIG_NET_CLS_BPF=m` [optional, for tc filters] + * `CONFIG_NET_ACT_BPF=m` [optional, for tc actions] + * `CONFIG_BPF_JIT=y` + * `CONFIG_HAVE_BPF_JIT=y` + * `CONFIG_BPF_EVENTS=y` [optional, for kprobes] * LLVM 3.7 or newer, compiled with BPF support (currently experimental) -* Clang 3.5 or newer (this requirement is orthoganal to the LLVM requirement, - and the versions do not necessarily need to match) -* cmake, gcc-4.9, flex, bison, xxd, libstdc++-static, libmnl-devel +* Clang 3.7, built from the same tree as LLVM +* pyroute2, version X.X (currently master, tag TBD) or newer +* cmake, gcc-4.7, flex, bison ## Getting started -Included in the scripts/ directory of this project is a VM kickstart script that -captures the above requirements inside a Fedora VM. Before running the script, -ensure that virt-install is available on the system. +### Demo VM -`./build_bpf_demo.sh -n bpf-demo -k bpf_demo.ks.erb` +See https://github.com/iovisor/bcc/scripts/README.md for a script that can +be used to set up a libvirt VM with the required dependencies. -After setting up the initial VM, log in (the default password is 'iovisor') -and determine the DHCP IP. SSH to this IP as root. +### Quick Setup -To set up a kernel with the right options, run `bpf-kernel-setup`. +If the LLVM and Linux kernel requirements are satisfied, testing out this +package should be as simple as: ``` -[root@bpf-demo ~]# bpf-kernel-setup -Cloning into 'net-next'... +git clone https://github.com/iovisor/bcc.git +cd bcc; mkdir build; cd build +cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_PREFIX_PATH=/opt/local/llvm +make -j$(grep -c ^processor /proc/cpuinfo) +sudo make install +cd ../../ +sudo python examples/hello_world.py +<ctrl-C> ``` -After pulling the net-next branch, the kernel config menu should pop up. Ensure -that the below settings are proper. -``` -General setup ---> - [*] Enable bpf() system call -Networking support ---> - Networking options ---> - QoS and/or fair queueing ---> - <M> BPF-based classifier - <M> BPF based action - [*] enable BPF Just In Time compiler -``` -Once the .config is saved, the build will proceed and install the resulting -kernel. This kernel has updated userspace headers (e.g. the bpf() syscall) which -install into /usr/local/include...proper packaging for this will be -distro-dependent. -Next, run `bpf-llvm-setup` to pull and compile LLVM with BPF support enabled. -``` -[root@bpf-demo ~]# bpf-llvm-setup -Cloning into 'llvm'... -``` -The resulting libraries will be installed into /opt/local/llvm. +Change `CMAKE_PREFIX_PATH` if llvm is installed elsewhere. + +### Cleaning up + +Since packaging is currently not available, one can cleanup the collateral of +bcc by doing: -Next, reboot into the new kernel, either manually or by using the kexec helper. ``` -[root@bpf-demo ~]# kexec-4.1.0-rc1+ -Connection to 192.168.122.247 closed by remote host. -Connection to 192.168.122.247 closed. +sudo rm -rf /usr/{lib/libbpf.prog.so,include/bcc,share/bcc} +sudo pip uninstall bpf ``` -Reconnect and run the final step, building and testing bcc. +### Building LLVM + +See http://llvm.org/docs/GettingStarted.html for the full guide. + +The short version: + ``` -[root@bpf-demo ~]# bcc-setup -Cloning into 'bcc'... -... -Linking CXX shared library libbpfprog.so -[100%] Built target bpfprog -... -Running tests... -Test project /root/bcc/build - Start 1: py_test1 -1/4 Test #1: py_test1 ......................... Passed 0.24 sec - Start 2: py_test2 -2/4 Test #2: py_test2 ......................... Passed 0.53 sec - Start 3: py_trace1 -3/4 Test #3: py_trace1 ........................ Passed 0.09 sec - Start 4: py_trace2 -4/4 Test #4: py_trace2 ........................ Passed 1.06 sec - -100% tests passed, 0 tests failed out of 4 +git clone https://github.com/llvm-mirror/llvm.git llvm +git clone https://github.com/llvm-mirror/clang.git llvm/tools/clang +mkdir llvm/build/ +cd llvm/build/ +cmake .. -DCMAKE_INSTALL_PREFIX=/opt/local/llvm +make -j$(grep -c ^processor /proc/cpuinfo) +sudo make install ``` - ## Release notes * 0.1 diff --git a/examples/hello_world.py b/examples/hello_world.py index 39dc85c975e3aff4735dbafe48cc7789e1a596d9..dcecc7070f71b8c1454eb57497a4300927076afe 100755 --- a/examples/hello_world.py +++ b/examples/hello_world.py @@ -9,7 +9,6 @@ from bpf import BPF from subprocess import call prog = """ -#include "src/cc/bpf_helpers.h" BPF_EXPORT(hello) int hello(void *ctx) { char fmt[] = "Hello, World!\\n"; diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000000000000000000000000000000000000..fbcc2cef2fb742d36fdb3b298f87fad4774841fe --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,68 @@ + +## Fedora Demo VM + +Before running the script, ensure that virt-install is available on the system. + +`./build_bpf_demo.sh -n bpf-demo -k bpf_demo.ks.erb` + +After setting up the initial VM, log in (the default password is 'iovisor') +and determine the DHCP IP. SSH to this IP as root. + +To set up a kernel with the right options, run `bpf-kernel-setup`. + +``` +[root@bpf-demo ~]# bpf-kernel-setup +Cloning into 'net-next'... +``` +After pulling the net-next branch, the kernel config menu should pop up. Ensure +that the below settings are proper. +``` +General setup ---> + [*] Enable bpf() system call +Networking support ---> + Networking options ---> + QoS and/or fair queueing ---> + <M> BPF-based classifier + <M> BPF based action + [*] enable BPF Just In Time compiler +``` +Once the .config is saved, the build will proceed and install the resulting +kernel. This kernel has updated userspace headers (e.g. the bpf() syscall) which +install into /usr/local/include...proper packaging for this will be +distro-dependent. + +Next, run `bpf-llvm-setup` to pull and compile LLVM with BPF support enabled. +``` +[root@bpf-demo ~]# bpf-llvm-setup +Cloning into 'llvm'... +``` +The resulting libraries will be installed into /opt/local/llvm. + +Next, reboot into the new kernel, either manually or by using the kexec helper. +``` +[root@bpf-demo ~]# kexec-4.1.0-rc1+ +Connection to 192.168.122.247 closed by remote host. +Connection to 192.168.122.247 closed. +``` + +Reconnect and run the final step, building and testing bcc. +``` +[root@bpf-demo ~]# bcc-setup +Cloning into 'bcc'... +... +Linking CXX shared library libbpfprog.so +[100%] Built target bpfprog +... +Running tests... +Test project /root/bcc/build + Start 1: py_test1 +1/4 Test #1: py_test1 ......................... Passed 0.24 sec + Start 2: py_test2 +2/4 Test #2: py_test2 ......................... Passed 0.53 sec + Start 3: py_trace1 +3/4 Test #3: py_trace1 ........................ Passed 0.09 sec + Start 4: py_trace2 +4/4 Test #4: py_trace2 ........................ Passed 1.06 sec + +100% tests passed, 0 tests failed out of 4 +``` diff --git a/scripts/bpf_demo.ks.erb b/scripts/bpf_demo.ks.erb index 5f3d2c508c612fb1ad959331371f23b9fc5d1d03..8cddf1068027c898097b1c6e4d6cd37dd03d3700 100644 --- a/scripts/bpf_demo.ks.erb +++ b/scripts/bpf_demo.ks.erb @@ -85,6 +85,7 @@ set -e -x numcpu=$(grep -c ^processor /proc/cpuinfo) git clone https://github.com/llvm-mirror/llvm.git +git clone https://github.com/llvm-mirror/clang.git llvm/tools/clang mkdir llvm/build/ cd llvm/build/ @@ -93,7 +94,6 @@ cmake .. \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_TERMINFO=OFF \ -DLLVM_TARGETS_TO_BUILD="ARM;CppBackend;X86;BPF" \ - -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=BPF \ -DCMAKE_INSTALL_PREFIX=/opt/local/llvm make -j$numcpu diff --git a/src/cc/CMakeLists.txt b/src/cc/CMakeLists.txt index 804204f2e00f355469cc922e7100d41245e2e40a..f0a97c239e39ef3368e0b98ed9bdc4eb756675c5 100644 --- a/src/cc/CMakeLists.txt +++ b/src/cc/CMakeLists.txt @@ -9,10 +9,20 @@ BISON_TARGET(Parser parser.yy ${CMAKE_CURRENT_BINARY_DIR}/parser.yy.cc COMPILE_F FLEX_TARGET(Lexer lexer.ll ${CMAKE_CURRENT_BINARY_DIR}/lexer.ll.cc COMPILE_FLAGS "--c++ --o lexer.ll.cc") ADD_FLEX_BISON_DEPENDENCY(Lexer Parser) -# if gcc 4.9 or higher is used, static libstdc++ is a good option -#set(CMAKE_SHARED_LINKER_FLAGS "-static-libstdc++ -Wl,--exclude-libs=ALL") +# prune unused llvm static library stuff when linking into the new .so set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--exclude-libs=ALL") +# if gcc 4.9 or higher is used, static libstdc++ is a good option +if (CMAKE_COMPILER_IS_GNUCC) + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) + if (GCC_VERSION VERSION_GREATER 4.9 OR GCC_VERSION VERSION_EQUAL 4.9) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++") + endif() +endif() + +# tell the shared library where it is being installed so it can find shared header files +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBCC_INSTALL_PREFIX='\"${CMAKE_INSTALL_PREFIX}\"'") + add_library(bpfprog SHARED bpf_common.cc bpf_module.cc codegen_llvm.cc node.cc parser.cc printer.cc type_check.cc libbpf.c b_frontend_action.cc kbuild_helper.cc @@ -30,3 +40,5 @@ set(clang_libs ${libclangFrontend} ${libclangSerialization} ${libclangDriver} ${ target_link_libraries(bpfprog ${clang_libs} ${llvm_libs} LLVMBPFCodeGen) install(TARGETS bpfprog LIBRARY DESTINATION lib) +install(DIRECTORY export/ DESTINATION share/bcc/include/bcc + FILES_MATCHING PATTERN "*.h") diff --git a/src/cc/bpf_module.cc b/src/cc/bpf_module.cc index 93029cdc4e7d7c7a35025049b8fe3e4fb35ed483..32bdca4c60aa3286efcc2df5779574ae148da8fd 100644 --- a/src/cc/bpf_module.cc +++ b/src/cc/bpf_module.cc @@ -151,6 +151,10 @@ int BPFModule::load_file_module(unique_ptr<llvm::Module> *mod, const string &fil vector<string> kflags; if (kbuild_helper.get_flags(un.release, &kflags)) return -1; + kflags.push_back("-include"); + kflags.push_back(BCC_INSTALL_PREFIX "/share/bcc/include/bcc/helpers.h"); + kflags.push_back("-I"); + kflags.push_back(BCC_INSTALL_PREFIX "/share/bcc/include"); for (auto it = kflags.begin(); it != kflags.end(); ++it) flags_cstr.push_back(it->c_str()); @@ -329,8 +333,7 @@ int BPFModule::parse() { return -1; } - // TODO: clean this - if (load_includes("../../src/cc/bpf_helpers.h") < 0) + if (load_includes(BCC_INSTALL_PREFIX "/share/bcc/include/bcc/helpers.h") < 0) return -1; codegen_ = ebpf::make_unique<ebpf::cc::CodegenLLVM>(mod_, parser_->scopes_.get(), proto_parser_->scopes_.get()); diff --git a/src/cc/bpf_helpers.h b/src/cc/export/helpers.h similarity index 100% rename from src/cc/bpf_helpers.h rename to src/cc/export/helpers.h diff --git a/src/cc/export/proto.h b/src/cc/export/proto.h new file mode 100644 index 0000000000000000000000000000000000000000..c6de80ebe528a18b13cc65b5083bb1da1d64bf01 --- /dev/null +++ b/src/cc/export/proto.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015 PLUMgrid, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +struct ethernet_t { + unsigned long long dst:48; + unsigned long long src:48; + unsigned int type:16; +} __attribute__((packed)); + +struct dot1q_t { + unsigned short pri:3; + unsigned short cfi:1; + unsigned short vlanid:12; + unsigned short type; +} __attribute__((packed)); + +struct arp_t { + unsigned short htype; + unsigned short ptype; + unsigned char hlen; + unsigned char plen; + unsigned short oper; + unsigned long long sha:48; + unsigned long long spa:32; + unsigned long long tha:48; + unsigned int tpa; +} __attribute__((packed)); + +struct ip_t { + unsigned char ver:4; // byte 0 + unsigned char hlen:4; + unsigned char tos; + unsigned short tlen; + unsigned short identification; // byte 4 + unsigned short ffo_unused:1; + unsigned short df:1; + unsigned short mf:1; + unsigned short foffset:13; + unsigned char ttl; // byte 8 + unsigned char nextp; + unsigned short hchecksum; + unsigned int src; // byte 12 + unsigned int dst; // byte 16 +} __attribute__((packed)); + +struct udp_t { + unsigned short sport; + unsigned short dport; + unsigned short length; + unsigned short crc; +} __attribute__((packed)); + +struct tcp_t { + unsigned short src_port; // byte 0 + unsigned short dst_port; + unsigned int seq_num; // byte 4 + unsigned int ack_num; // byte 8 + unsigned char offset:4; // byte 12 + unsigned char reserved:4; + unsigned char flag_cwr:1; + unsigned char flag_ece:1; + unsigned char flag_urg:1; + unsigned char flag_ack:1; + unsigned char flag_psh:1; + unsigned char flag_rst:1; + unsigned char flag_syn:1; + unsigned char flag_fin:1; + unsigned short rcv_wnd; + unsigned short cksum; // byte 16 + unsigned short urg_ptr; +} __attribute__((packed)); diff --git a/src/cc/proto.h b/src/cc/proto.h deleted file mode 100644 index d23fe2b552fd8ecfb54abfb262d5879a593a0c2a..0000000000000000000000000000000000000000 --- a/src/cc/proto.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2015 PLUMgrid, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <linux/types.h> - -struct ethernet_t { - u64 dst:48; - u64 src:48; - u32 type:16; -} __attribute__((packed)); - -struct dot1q_t { - u16 pri:3; - u16 cfi:1; - u16 vlanid:12; - u16 type; -} __attribute__((packed)); - -struct arp_t { - u16 htype; - u16 ptype; - u8 hlen; - u8 plen; - u16 oper; - u64 sha:48; - u64 spa:32; - u64 tha:48; - u32 tpa; -} __attribute__((packed)); - -struct ip_t { - u8 ver:4; // byte 0 - u8 hlen:4; - u8 tos; - u16 tlen; - u16 identification; // byte 4 - u16 ffo_unused:1; - u16 df:1; - u16 mf:1; - u16 foffset:13; - u8 ttl; // byte 8 - u8 nextp; - u16 hchecksum; - u32 src; // byte 12 - u32 dst; // byte 16 -} __attribute__((packed)); - -struct udp_t { - u16 sport; - u16 dport; - u16 length; - u16 crc; -} __attribute__((packed)); - -struct tcp_t { - u16 src_port; // byte 0 - u16 dst_port; - u32 seq_num; // byte 4 - u32 ack_num; // byte 8 - u8 offset:4; // byte 12 - u8 reserved:4; - u8 flag_cwr:1; - u8 flag_ece:1; - u8 flag_urg:1; - u8 flag_ack:1; - u8 flag_psh:1; - u8 flag_rst:1; - u8 flag_syn:1; - u8 flag_fin:1; - u16 rcv_wnd; - u16 cksum; // byte 16 - u16 urg_ptr; -} __attribute__((packed)); diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 891693e69a93d79c0d2bf765f1055883226cf391..f62048e2623114ae30b9f7bbf3cb97f4a989ef79 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -7,13 +7,14 @@ endmacro() symlink_file(${CMAKE_CURRENT_SOURCE_DIR}/bpf ${CMAKE_CURRENT_BINARY_DIR}/bpf) +set(PIP_INSTALLABLE "${CMAKE_CURRENT_BINARY_DIR}/dist/bpf-${REVISION}.tar.gz") configure_file(setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py @ONLY) # build the pip installable -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dist/bpf-${REVISION}.tar.gz +add_custom_command(OUTPUT ${PIP_INSTALLABLE} COMMAND python setup.py sdist WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bpf/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/setup.py ) -add_custom_target(bpf_py ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dist/bpf-${REVISION}.tar.gz) +add_custom_target(bpf_py ALL DEPENDS ${PIP_INSTALLABLE}) install(CODE "execute_process(COMMAND python setup.py install -f --prefix=${CMAKE_INSTALL_PREFIX} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") diff --git a/tests/cc/test_call1.c b/tests/cc/test_call1.c index 38d221a5627cc9c6d285a498d3fc01acf541b3eb..4b6b65396b3c294fa27324579386c06f42312559 100644 --- a/tests/cc/test_call1.c +++ b/tests/cc/test_call1.c @@ -1,6 +1,5 @@ // Copyright (c) PLUMgrid, Inc. // Licensed under the Apache License, Version 2.0 (the "License") -#include "../../src/cc/bpf_helpers.h" BPF_TABLE("prog", int, int, jump, 64); BPF_TABLE("array", int, u64, stats, 64); diff --git a/tests/cc/test_stat1.c b/tests/cc/test_stat1.c index 92c85d46047c1f33cc2eaf0c3bfee690efd6b31f..970bb72cdd4f52a3b88388ef055838b19d741eb1 100644 --- a/tests/cc/test_stat1.c +++ b/tests/cc/test_stat1.c @@ -1,7 +1,7 @@ // Copyright (c) PLUMgrid, Inc. // Licensed under the Apache License, Version 2.0 (the "License") -#include "../../src/cc/bpf_helpers.h" -#include "../../src/cc/proto.h" + +#include <bcc/proto.h> struct IPKey { u32 dip; diff --git a/tests/cc/test_trace2.c b/tests/cc/test_trace2.c index ead26d5c9cedc9bd18831724894b47fa8f6b9365..e4f5db11c035e01fd9362fb665cb80b94ff6ddd3 100644 --- a/tests/cc/test_trace2.c +++ b/tests/cc/test_trace2.c @@ -1,7 +1,6 @@ // Copyright (c) PLUMgrid, Inc. // Licensed under the Apache License, Version 2.0 (the "License") #include <linux/ptrace.h> -#include "../../src/cc/bpf_helpers.h" struct Ptr { u64 ptr; }; struct Counters { u64 stat1; }; BPF_TABLE("hash", struct Ptr, struct Counters, stats, 1024); diff --git a/tests/cc/test_trace2.py b/tests/cc/test_trace2.py index 64ed192013b44b1496ce3662f2f0b3f5bf3f680c..35db950878d4bd8ceb40f4a0410c3214ee80edd6 100755 --- a/tests/cc/test_trace2.py +++ b/tests/cc/test_trace2.py @@ -10,7 +10,6 @@ from unittest import main, TestCase text = """ #include <linux/ptrace.h> -#include "../../src/cc/bpf_helpers.h" struct Ptr { u64 ptr; }; struct Counters { u64 stat1; }; BPF_TABLE("hash", struct Ptr, struct Counters, stats, 1024); diff --git a/tests/cc/test_trace3.c b/tests/cc/test_trace3.c index 543135e15b4c51cfcdbf530635132405b97bee7d..1058be2c2337e41128788017fac2b32876c4604d 100644 --- a/tests/cc/test_trace3.c +++ b/tests/cc/test_trace3.c @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0 (the "License") #include <linux/ptrace.h> #include <linux/blkdev.h> -#include "../../src/cc/bpf_helpers.h" struct Request { u64 rq; }; struct Time { u64 start; }; BPF_TABLE("hash", struct Request, struct Time, requests, 1024); diff --git a/tests/cc/test_xlate1.c b/tests/cc/test_xlate1.c index 2492122f692883a83939f6d05195dafebee3f230..a7f06359c3fd7033a5023e606a02131e6b131b63 100644 --- a/tests/cc/test_xlate1.c +++ b/tests/cc/test_xlate1.c @@ -1,7 +1,6 @@ // Copyright (c) PLUMgrid, Inc. // Licensed under the Apache License, Version 2.0 (the "License") -#include "../../src/cc/bpf_helpers.h" -#include "../../src/cc/proto.h" +#include <bcc/proto.h> struct IPKey { u32 dip; u32 sip;