Commit f275d3db authored by Brenden Blanco's avatar Brenden Blanco

Add multiple build support styles

* Add RPM and DEB packaging targets (using CPack from CMake) to build
  binary packages for Fedora and Ubuntu targets.
* Add Docker build scripts for each of the above that run the build in
  the right environment (assuming docker is available).
 - In Ubuntu, build against the LLVM 3.7 nightly snapshots
 - In Fedora, build against LLVM 3.7 from git (takes longer)
* Depending on packages installed on the build machine, it may be
  possible to cross-package for other targets without invoking Docker.
* Re-introduce src/cc/compat directory to keep the build stable for the
  time being. Similarly, it was necessary to #define some ugly constants
  that should eventually show up in libc.
* Add a few simple version checks to allow a partially working (really
  tracing only) libbcc in 4.1 kernels.

TODO (followup commit): Re-work the READMEs
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent 439a9f30
Dockerfile*
build
.*.swp
......@@ -2,8 +2,8 @@
# Licensed under the Apache License, Version 2.0 (the "License")
cmake_minimum_required(VERSION 2.8.7)
project(bpf-tools)
set(CMAKE_BUILD_TYPE Debug)
project(bcc)
set(CMAKE_BUILD_TYPE Release)
enable_testing()
......@@ -21,7 +21,7 @@ message(STATUS "Found LLVM: ${LLVM_INCLUDE_DIRS}")
# clang is linked as a library, but the library path searching is
# primitively supported, unlike libLLVM
set(CLANG_SEARCH "/opt/local/llvm/lib;${LLVM_LIBRARY_DIRS}")
set(CLANG_SEARCH "/opt/local/llvm/lib;/usr/lib/llvm-3.7/lib;${LLVM_LIBRARY_DIRS}")
find_library(libclangAnalysis NAMES clangAnalysis HINTS ${CLANG_SEARCH})
find_library(libclangAST NAMES clangAST HINTS ${CLANG_SEARCH})
find_library(libclangBasic NAMES clangBasic HINTS ${CLANG_SEARCH})
......@@ -48,3 +48,17 @@ endif()
add_subdirectory(scripts)
add_subdirectory(src)
add_subdirectory(tests)
set(CPACK_PACKAGE_NAME "libbcc")
set(CPACK_PACKAGE_VERSION "${REVISION}")
set(CPACK_PACKAGE_CONTACT "Brenden Blanco <bblanco@plumgrid.com")
if(EXISTS "/etc/redhat-release")
set(CPACK_GENERATOR "RPM")
else()
set(CPACK_GENERATOR "DEB")
endif()
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libstdc++6, python")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Shared Library for BPF Compiler Collection (BCC)")
include(CPack)
# File to be used for building an Ubuntu .deb
FROM fedora
MAINTAINER Brenden Blanco <bblanco@plumgrid.com>
RUN dnf -y install @rpm-development-tools @c-development @development-tools cmake libstdc++-static
WORKDIR /root
RUN git clone https://github.com/llvm-mirror/llvm.git
RUN git clone https://github.com/llvm-mirror/clang.git llvm/tools/clang
RUN mkdir -p /root/llvm/build
WORKDIR /root/llvm/build
RUN cmake .. -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="ARM;CppBackend;X86;BPF"
RUN make -j$(grep -c ^process /proc/cpuinfo)
RUN mkdir -p /root/bcc/build
COPY ./ /root/bcc/
WORKDIR /root/bcc/build
RUN cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_PREFIX_PATH=/root/llvm/build
RUN make -j$(grep -c ^process /proc/cpuinfo) package
# File to be used for building an Ubuntu .deb
FROM ubuntu:trusty
MAINTAINER Brenden Blanco <bblanco@plumgrid.com>
RUN apt-get -y install wget
RUN printf "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty main\ndeb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty main\n" > /etc/apt/sources.list.d/llvm.list
RUN wget -q -O - http://llvm.org/apt/llvm-snapshot.gpg.key | apt-key add -
RUN apt-get -y update
RUN apt-get -y install bison build-essential cmake flex git libedit-dev python zlib1g-dev
RUN apt-get -y install libllvm3.7 llvm-3.7-dev libclang-3.7-dev
RUN mkdir -p /root/bcc/build
COPY ./ /root/bcc/
WORKDIR /root/bcc/build
RUN cmake .. -DCMAKE_INSTALL_PREFIX=/usr
RUN make -j$(grep -c ^process /proc/cpuinfo) package
......@@ -5,15 +5,17 @@ string(SUBSTRING "${GIT_SHA1}" 0 8 GIT_SHA1_SHORT)
git_describe(GIT_DESCRIPTION)
git_describe(GIT_TAG_LAST "--abbrev=0")
git_get_exact_tag(GIT_TAG_EXACT)
string(SUBSTRING "${GIT_TAG_LAST}-${GIT_SHA1_SHORT}" 1 -1 REVISION)
if(GIT_TAG_EXACT)
string(SUBSTRING "${GIT_TAG_EXACT}" 1 -1 REVISION)
message(STATUS "Currently on Git tag ${GIT_TAG_EXACT}")
else ()
message(STATUS "Latest recognized Git tag is ${GIT_TAG_LAST}")
set(GIT_TAG_EXACT "")
if(NOT REVISION)
string(SUBSTRING "${GIT_TAG_LAST}-${GIT_SHA1_SHORT}" 1 -1 REVISION)
if(GIT_TAG_EXACT)
string(SUBSTRING "${GIT_TAG_EXACT}" 1 -1 REVISION)
message(STATUS "Currently on Git tag ${GIT_TAG_EXACT}")
else ()
message(STATUS "Latest recognized Git tag is ${GIT_TAG_LAST}")
set(GIT_TAG_EXACT "")
endif()
message(STATUS "Git HEAD is ${GIT_SHA1}")
endif()
message(STATUS "Git HEAD is ${GIT_SHA1}")
# strip leading 'v', and make unique for the tag
message(STATUS "Revision is ${REVISION}")
......
......@@ -117,7 +117,6 @@ numcpu=$(grep -c ^processor /proc/cpuinfo)
git clone https://github.com/iovisor/bcc.git
mkdir bcc/build/
cd bcc/build/
git checkout bblanco_dev
export PATH=/opt/local/llvm/bin:$PATH
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
make -j$numcpu
......
......@@ -3,6 +3,8 @@
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${LLVM_INCLUDE_DIRS})
# todo: if check for kernel version
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/compat)
add_definitions(${LLVM_DEFINITIONS})
BISON_TARGET(Parser parser.yy ${CMAKE_CURRENT_BINARY_DIR}/parser.yy.cc COMPILE_FLAGS "-o parser.yy.cc -v --debug")
......
......@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <linux/bpf.h>
#include <linux/version.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/ASTContext.h>
......@@ -373,8 +374,10 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
map_type = BPF_MAP_TYPE_HASH;
else if (A->getName() == "maps/array")
map_type = BPF_MAP_TYPE_ARRAY;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0)
else if (A->getName() == "maps/prog")
map_type = BPF_MAP_TYPE_PROG_ARRAY;
#endif
table.fd = bpf_create_map(map_type, table.key_size, table.leaf_size, table.max_entries);
if (table.fd < 0) {
llvm::errs() << "error: could not open bpf fd\n";
......
/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
#ifndef _UAPI__LINUX_BPF_H__
#define _UAPI__LINUX_BPF_H__
#include <linux/types.h>
#include <linux/bpf_common.h>
/* Extended instruction set based on top of classic BPF */
/* instruction classes */
#define BPF_ALU64 0x07 /* alu mode in double word width */
/* ld/ldx fields */
#define BPF_DW 0x18 /* double word */
#define BPF_XADD 0xc0 /* exclusive add */
/* alu/jmp fields */
#define BPF_MOV 0xb0 /* mov reg to reg */
#define BPF_ARSH 0xc0 /* sign extending arithmetic shift right */
/* change endianness of a register */
#define BPF_END 0xd0 /* flags for endianness conversion: */
#define BPF_TO_LE 0x00 /* convert to little-endian */
#define BPF_TO_BE 0x08 /* convert to big-endian */
#define BPF_FROM_LE BPF_TO_LE
#define BPF_FROM_BE BPF_TO_BE
#define BPF_JNE 0x50 /* jump != */
#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
#define BPF_CALL 0x80 /* function call */
#define BPF_EXIT 0x90 /* function return */
/* Register numbers */
enum {
BPF_REG_0 = 0,
BPF_REG_1,
BPF_REG_2,
BPF_REG_3,
BPF_REG_4,
BPF_REG_5,
BPF_REG_6,
BPF_REG_7,
BPF_REG_8,
BPF_REG_9,
BPF_REG_10,
__MAX_BPF_REG,
};
/* BPF has 10 general purpose 64-bit registers and stack frame. */
#define MAX_BPF_REG __MAX_BPF_REG
struct bpf_insn {
__u8 code; /* opcode */
__u8 dst_reg:4; /* dest register */
__u8 src_reg:4; /* source register */
__s16 off; /* signed offset */
__s32 imm; /* signed immediate constant */
};
/* BPF syscall commands */
enum bpf_cmd {
/* create a map with given type and attributes
* fd = bpf(BPF_MAP_CREATE, union bpf_attr *, u32 size)
* returns fd or negative error
* map is deleted when fd is closed
*/
BPF_MAP_CREATE,
/* lookup key in a given map
* err = bpf(BPF_MAP_LOOKUP_ELEM, union bpf_attr *attr, u32 size)
* Using attr->map_fd, attr->key, attr->value
* returns zero and stores found elem into value
* or negative error
*/
BPF_MAP_LOOKUP_ELEM,
/* create or update key/value pair in a given map
* err = bpf(BPF_MAP_UPDATE_ELEM, union bpf_attr *attr, u32 size)
* Using attr->map_fd, attr->key, attr->value, attr->flags
* returns zero or negative error
*/
BPF_MAP_UPDATE_ELEM,
/* find and delete elem by key in a given map
* err = bpf(BPF_MAP_DELETE_ELEM, union bpf_attr *attr, u32 size)
* Using attr->map_fd, attr->key
* returns zero or negative error
*/
BPF_MAP_DELETE_ELEM,
/* lookup key in a given map and return next key
* err = bpf(BPF_MAP_GET_NEXT_KEY, union bpf_attr *attr, u32 size)
* Using attr->map_fd, attr->key, attr->next_key
* returns zero and stores next key or negative error
*/
BPF_MAP_GET_NEXT_KEY,
/* verify and load eBPF program
* prog_fd = bpf(BPF_PROG_LOAD, union bpf_attr *attr, u32 size)
* Using attr->prog_type, attr->insns, attr->license
* returns fd or negative error
*/
BPF_PROG_LOAD,
};
enum bpf_map_type {
BPF_MAP_TYPE_UNSPEC,
BPF_MAP_TYPE_HASH,
BPF_MAP_TYPE_ARRAY,
BPF_MAP_TYPE_PROG_ARRAY,
};
enum bpf_prog_type {
BPF_PROG_TYPE_UNSPEC,
BPF_PROG_TYPE_SOCKET_FILTER,
BPF_PROG_TYPE_KPROBE,
BPF_PROG_TYPE_SCHED_CLS,
BPF_PROG_TYPE_SCHED_ACT,
};
#define BPF_PSEUDO_MAP_FD 1
/* flags for BPF_MAP_UPDATE_ELEM command */
#define BPF_ANY 0 /* create new element or update existing */
#define BPF_NOEXIST 1 /* create new element if it didn't exist */
#define BPF_EXIST 2 /* update existing element */
union bpf_attr {
struct { /* anonymous struct used by BPF_MAP_CREATE command */
__u32 map_type; /* one of enum bpf_map_type */
__u32 key_size; /* size of key in bytes */
__u32 value_size; /* size of value in bytes */
__u32 max_entries; /* max number of entries in a map */
};
struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
__u32 map_fd;
__aligned_u64 key;
union {
__aligned_u64 value;
__aligned_u64 next_key;
};
__u64 flags;
};
struct { /* anonymous struct used by BPF_PROG_LOAD command */
__u32 prog_type; /* one of enum bpf_prog_type */
__u32 insn_cnt;
__aligned_u64 insns;
__aligned_u64 license;
__u32 log_level; /* verbosity level of verifier */
__u32 log_size; /* size of user buffer */
__aligned_u64 log_buf; /* user supplied buffer */
__u32 kern_version; /* checked when prog_type=kprobe */
};
} __attribute__((aligned(8)));
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
*/
enum bpf_func_id {
BPF_FUNC_unspec,
BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
BPF_FUNC_probe_read, /* int bpf_probe_read(void *dst, int size, void *src) */
BPF_FUNC_ktime_get_ns, /* u64 bpf_ktime_get_ns(void) */
BPF_FUNC_trace_printk, /* int bpf_trace_printk(const char *fmt, int fmt_size, ...) */
BPF_FUNC_get_prandom_u32, /* u32 prandom_u32(void) */
BPF_FUNC_get_smp_processor_id, /* u32 raw_smp_processor_id(void) */
/**
* skb_store_bytes(skb, offset, from, len, flags) - store bytes into packet
* @skb: pointer to skb
* @offset: offset within packet from skb->mac_header
* @from: pointer where to copy bytes from
* @len: number of bytes to store into packet
* @flags: bit 0 - if true, recompute skb->csum
* other bits - reserved
* Return: 0 on success
*/
BPF_FUNC_skb_store_bytes,
/**
* l3_csum_replace(skb, offset, from, to, flags) - recompute IP checksum
* @skb: pointer to skb
* @offset: offset within packet where IP checksum is located
* @from: old value of header field
* @to: new value of header field
* @flags: bits 0-3 - size of header field
* other bits - reserved
* Return: 0 on success
*/
BPF_FUNC_l3_csum_replace,
/**
* l4_csum_replace(skb, offset, from, to, flags) - recompute TCP/UDP checksum
* @skb: pointer to skb
* @offset: offset within packet where TCP/UDP checksum is located
* @from: old value of header field
* @to: new value of header field
* @flags: bits 0-3 - size of header field
* bit 4 - is pseudo header
* other bits - reserved
* Return: 0 on success
*/
BPF_FUNC_l4_csum_replace,
/**
* bpf_tail_call(ctx, prog_array_map, index) - jump into another BPF program
* @ctx: context pointer passed to next program
* @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
* @index: index inside array that selects specific program to run
* Return: 0 on success
*/
BPF_FUNC_tail_call,
/**
* bpf_clone_redirect(skb, ifindex, flags) - redirect to another netdev
* @skb: pointer to skb
* @ifindex: ifindex of the net device
* @flags: bit 0 - if set, redirect to ingress instead of egress
* other bits - reserved
* Return: 0 on success
*/
BPF_FUNC_clone_redirect,
/**
* u64 bpf_get_current_pid_tgid(void)
* Return: current->tgid << 32 | current->pid
*/
BPF_FUNC_get_current_pid_tgid,
/**
* u64 bpf_get_current_uid_gid(void)
* Return: current_gid << 32 | current_uid
*/
BPF_FUNC_get_current_uid_gid,
/**
* bpf_get_current_comm(char *buf, int size_of_buf)
* stores current->comm into buf
* Return: 0 on success
*/
BPF_FUNC_get_current_comm,
__BPF_FUNC_MAX_ID,
};
/* user accessible mirror of in-kernel sk_buff.
* new fields can only be added to the end of this structure
*/
struct __sk_buff {
__u32 len;
__u32 pkt_type;
__u32 mark;
__u32 queue_mapping;
__u32 protocol;
__u32 vlan_present;
__u32 vlan_tci;
__u32 vlan_proto;
__u32 priority;
__u32 ingress_ifindex;
__u32 ifindex;
__u32 tc_index;
__u32 cb[5];
};
#endif /* _UAPI__LINUX_BPF_H__ */
#ifndef _UAPI__LINUX_BPF_COMMON_H__
#define _UAPI__LINUX_BPF_COMMON_H__
/* Instruction classes */
#define BPF_CLASS(code) ((code) & 0x07)
#define BPF_LD 0x00
#define BPF_LDX 0x01
#define BPF_ST 0x02
#define BPF_STX 0x03
#define BPF_ALU 0x04
#define BPF_JMP 0x05
#define BPF_RET 0x06
#define BPF_MISC 0x07
/* ld/ldx fields */
#define BPF_SIZE(code) ((code) & 0x18)
#define BPF_W 0x00
#define BPF_H 0x08
#define BPF_B 0x10
#define BPF_MODE(code) ((code) & 0xe0)
#define BPF_IMM 0x00
#define BPF_ABS 0x20
#define BPF_IND 0x40
#define BPF_MEM 0x60
#define BPF_LEN 0x80
#define BPF_MSH 0xa0
/* alu/jmp fields */
#define BPF_OP(code) ((code) & 0xf0)
#define BPF_ADD 0x00
#define BPF_SUB 0x10
#define BPF_MUL 0x20
#define BPF_DIV 0x30
#define BPF_OR 0x40
#define BPF_AND 0x50
#define BPF_LSH 0x60
#define BPF_RSH 0x70
#define BPF_NEG 0x80
#define BPF_MOD 0x90
#define BPF_XOR 0xa0
#define BPF_JA 0x00
#define BPF_JEQ 0x10
#define BPF_JGT 0x20
#define BPF_JGE 0x30
#define BPF_JSET 0x40
#define BPF_SRC(code) ((code) & 0x08)
#define BPF_K 0x00
#define BPF_X 0x08
#ifndef BPF_MAXINSNS
#define BPF_MAXINSNS 4096
#endif
#endif /* _UAPI__LINUX_BPF_COMMON_H__ */
......@@ -63,6 +63,7 @@ static u64 (*bpf_ktime_get_ns)(void) =
static int (*bpf_trace_printk_)(const char *fmt, u64 fmt_size, ...) =
(void *) BPF_FUNC_trace_printk;
int bpf_trace_printk(const char *fmt, ...) asm("llvm.bpf.extra");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0)
static u64 (*bpf_clone_redirect)(void *ctx, u64 ifindex, u64 flags) =
(void *) BPF_FUNC_clone_redirect;
static u64 (*bpf_get_smp_processor_id)(void) =
......@@ -76,6 +77,7 @@ static int (*bpf_get_current_comm)(void *buf, int buf_size) =
static void bpf_tail_call_(u64 map_fd, void *ctx, int index) {
((void (*)(void *, u64, int))BPF_FUNC_tail_call)(ctx, map_fd, index);
}
#endif
/* llvm builtin functions that eBPF C program may use to
* emit BPF_LD_ABS and BPF_LD_IND instructions
......
......@@ -34,6 +34,24 @@
#include "libbpf.h"
// TODO: remove these defines when linux-libc-dev exports them properly
#ifndef __NR_bpf
#define __NR_bpf 321
#endif
#ifndef SO_ATTACH_BPF
#define SO_ATTACH_BPF 50
#endif
#ifndef PERF_EVENT_IOC_SET_BPF
#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
#endif
#ifndef PERF_FLAG_FD_CLOEXEC
#define PERF_FLAG_FD_CLOEXEC (1UL << 3)
#endif
static __u64 ptr_to_u64(void *ptr)
{
return (__u64) (unsigned long) ptr;
......
......@@ -16,5 +16,9 @@ add_custom_command(OUTPUT ${PIP_INSTALLABLE}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bpf/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/setup.py
)
add_custom_target(bpf_py ALL DEPENDS ${PIP_INSTALLABLE})
install(CODE "execute_process(COMMAND python setup.py install -f
if(EXISTS "/etc/debian_version")
set(PYTHON_FLAGS "${PYTHON_FLAGS} --install-layout deb")
endif()
install(CODE "execute_process(COMMAND python setup.py install -f ${PYTHON_FLAGS}
--prefix=${CMAKE_INSTALL_PREFIX} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
......@@ -16,8 +16,9 @@ import atexit
from collections import MutableMapping
import ctypes as ct
import json
from past.builtins import basestring
import os
import sys
basestring = (unicode if sys.version_info[0] < 3 else str)
lib = ct.CDLL("libbpfprog.so")
......@@ -187,22 +188,22 @@ class BPF(object):
return fn
str2ctype = {
"_Bool": ct.c_bool,
"char": ct.c_char,
"wchar_t": ct.c_wchar,
"char": ct.c_byte,
"unsigned char": ct.c_ubyte,
"short": ct.c_short,
"unsigned short": ct.c_ushort,
"int": ct.c_int,
"unsigned int": ct.c_uint,
"long": ct.c_long,
"unsigned long": ct.c_ulong,
"long long": ct.c_longlong,
"unsigned long long": ct.c_ulonglong,
"float": ct.c_float,
"double": ct.c_double,
"long double": ct.c_longdouble
u"_Bool": ct.c_bool,
u"char": ct.c_char,
u"wchar_t": ct.c_wchar,
u"char": ct.c_byte,
u"unsigned char": ct.c_ubyte,
u"short": ct.c_short,
u"unsigned short": ct.c_ushort,
u"int": ct.c_int,
u"unsigned int": ct.c_uint,
u"long": ct.c_long,
u"unsigned long": ct.c_ulong,
u"long long": ct.c_longlong,
u"unsigned long long": ct.c_ulonglong,
u"float": ct.c_float,
u"double": ct.c_double,
u"long double": ct.c_longdouble
}
@staticmethod
def _decode_table_type(desc):
......
# Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")
from distutils.core import setup
import os
import sys
if os.environ.get('DESTDIR'):
sys.argv += ['--root', os.environ['DESTDIR']]
setup(name='bpf',
version='@REVISION@',
......@@ -9,5 +14,4 @@ setup(name='bpf',
author_email='bblanco@plumgrid.com',
url='http://plumgrid.com',
packages=['bpf'],
platforms=['Linux'],
install_requires=['future'])
platforms=['Linux'])
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment