Commit 452de20f authored by Brenden Blanco's avatar Brenden Blanco

Updated README, example virt-install script

* Add Getting Started section in README.md
* Add a virt-install script which creates a BPF-capable Fedora 21 VM
* Fix a test that was failing on F21
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent c3c4fc19
......@@ -20,8 +20,8 @@ endif()
execute_process(COMMAND ${CLANG} --version OUTPUT_VARIABLE CLANG_VERSION_RAW)
string(REGEX MATCH "[0-9]+[.][0-9]+[.][0-9]+" CLANG_VERSION ${CLANG_VERSION_RAW})
message(STATUS "Found CLANG: ${CLANG} (found version \"${CLANG_VERSION}\")")
if (CLANG_VERSION VERSION_LESS 3.6.0)
message(FATAL_ERROR "requires clang version >= 3.6.0, ${CLANG_VERSION} found")
if (CLANG_VERSION VERSION_LESS 3.5.0)
message(FATAL_ERROR "requires clang version >= 3.5.0, ${CLANG_VERSION} found")
endif()
set(CMAKE_C_FLAGS "-Wall")
......
......@@ -10,11 +10,11 @@ features which are mostly available in Linux 4.1 and above.
## Motivation
BPF guarantees that the programs loaded into the kernel cannot crash, and
cannot run forever, but yet BPF is general purpose enough to perform many
arbitrary types of computation. Currently, it is possible to write a program in
cannot run forever, but yet BPF is general purpose enough to perform many
arbitrary types of computation. Currently, it is possible to write a program in
C that will compile into a valid BPF program, yet it is vastly easier to
write a C program that will compile into invalid BPF (C is like that). The user
won't know until trying to run the program whether it was valid or not.
won't know until trying to run the program whether it was valid or not.
With a BPF-specific frontend, one should be able to write in a language and
receive feedback from the compiler on the validity as it pertains to a BPF
......@@ -24,7 +24,7 @@ programs while still harnessing its full flexibility.
The features of this toolkit include:
* End-to-end BPF workflow in a shared library
* The B language - a C-like language for BPF backends
* Integration with llvm-bpf backend for JIT
* Integration with llvm-bpf backend for JIT
* Dynamic (un)loading of JITed programs
* Support for BPF kernel hooks: socket filters, tc classifiers,
tc actions, and kprobes
......@@ -45,9 +45,80 @@ To get started using this toolchain, one needs:
* 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)
and the versions do not necessarily need to match)
* cmake, gcc-4.9, flex, bison, xxd, libstdc++-static, libmnl-devel
## 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.
`./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
```
## Release notes
* 0.1
......
# Minimal Kickstart file
install
text
reboot
lang en_US.UTF-8
# repo to install the OS
url --url=<%= @mirror %>/Everything/x86_64/os/
keyboard us
network --bootproto dhcp
rootpw <%= @password %>
authconfig --enableshadow --passalgo=sha512 --enablefingerprint
firewall --enabled --ssh
selinux --enforcing
timezone --utc America/Los_Angeles
#firstboot --disable
bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH crashkernel=auto"
zerombr
clearpart --all --initlabel
autopart --type=lvm
repo --name=everything --baseurl=<%= @mirror %>/Everything/x86_64/os/
#Just core packages
%packages --nobase
@core
ntp
@c-development
@development-tools
@rpm-development-tools
ncurses-devel
vim
bc
kexec-tools
cmake
clang
libmnl-devel
libstdc++-static
python-netaddr
%end
%post --log=/root/anaconda-post.log
echo Kickstart post
chkconfig NetworkManager off
chkconfig network on
chkconfig ntpd on
yum -y clean metadata
yum -y update
hostname <%= @name %>.<%= @domain %>
echo "<%= @name %>.<%= @domain %>" > /etc/hostname
cat > /usr/local/bin/bpf-kernel-setup <<'DELIM__'
#!/bin/bash
set -e -x
numcpu=$(grep -c ^processor /proc/cpuinfo)
git clone https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
cd net-next/
cp /boot/config-$(uname -r) ./
cp ./config-$(uname -r) .config
make -j$numcpu mrproper
make -j$numcpu nconfig
make -j$numcpu bzImage
make -j$numcpu modules
sudo make modules_install
sudo make install
sudo make INSTALL_HDR_PATH=/usr/local headers_install
release=$(<include/config/kernel.release)
echo "kexec -l /boot/vmlinuz-$release --initrd=/boot/initramfs-$release.img --reuse-cmdline; reboot" > /usr/local/bin/kexec-$release
chmod +x /usr/local/bin/kexec-$release
ln -fs kexec-$release /usr/local/bin/kexec-latest
DELIM__
chmod +x /usr/local/bin/bpf-kernel-setup
cat > /usr/local/bin/bpf-llvm-setup <<'DELIM__'
#!/bin/bash
set -e -x
numcpu=$(grep -c ^processor /proc/cpuinfo)
git clone https://github.com/llvm-mirror/llvm.git
mkdir llvm/build/
cd llvm/build/
cmake .. \
-DBUILD_SHARED_LIBS=OFF \
-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
sudo make install
grep -q llvm $HOME/.bashrc || echo 'PATH=/opt/local/llvm/bin:$PATH' >> $HOME/.bashrc
DELIM__
chmod +x /usr/local/bin/bpf-llvm-setup
cat > /usr/local/bin/bcc-setup <<'DELIM__'
#!/bin/bash
set -e -x
numcpu=$(grep -c ^processor /proc/cpuinfo)
repo=ssh://git@github.com/plumgrid/bcc.git
git ls-remote $repo 2>&1 > /dev/null
if [[ $? -ne 0 ]]; then
repo=https://<%= @github_access_token %>@github.com/plumgrid/bcc.git
fi
git clone $repo
mkdir bcc/build/
cd bcc/build/
cmake ..
make -j$numcpu
make test
DELIM__
chmod +x /usr/local/bin/bcc-setup
%end
#!/bin/bash
#set -x
set -e
function usage() {
cat <<DELIM__
usage: $(basename $0) [options]
Options:
-b, --bridge BRNAME Which linux bridge to attach to
-c, --cpu NUM Number of CPUs to reserve to the instance (default 4)
-g, --github_token X HTTP Github oauth token (for buildbots)
-k, --kickstart KS Path to kickstart file to use (required)
-m, --mirror URL URL at which to reach netinstallable packages
-M, --mem NUM Number of MB to reserve to the instance (default 4094)
-n, --name NAME Name of the instance (required)
-p, --password PASS Password to set in the VM
-s, --size NUM Size in GB to reserve for the virtual HDD (default 40GB)
DELIM__
}
TEMP=$(getopt -o b:c:k:m:M:n:p:s: --long bridge:,cpu:,kickstart:,mirror:,mem:,name:,password:size: -- "$@")
if [[ $? -ne 0 ]]; then
usage
exit 1
fi
eval set -- "$TEMP"
while true; do
case "$1" in
-b|--bridge) BRIDGE="$2"; shift 2 ;;
-c|--cpu) CPU="$2"; shift 2 ;;
-k|--kickstart) KICKSTART="$2"; shift 2 ;;
-n|--name) NAME="$2"; shift 2 ;;
-m|--mirror) MIRROR="$2"; shift 2 ;;
-M|--mem) MEM="$2"; shift 2 ;;
-p|--password) PASSWORD="$2"; shift 2 ;;
-s|--size) SIZE="$2"; shift 2 ;;
--) shift; break ;;
*) usage; exit 1
;;
esac
done
[[ ! -f "$KICKSTART" ]] && { usage; exit 1; }
[[ -z "$NAME" ]] && { usage; exit 1; }
PASSWORD=${PASSWORD:-"iovisor"}
BRIDGE=${BRIDGE:-virbr0}
MIRROR=${MIRROR:-http://mirror.pnl.gov/fedora/linux/releases/21}
MEM=${MEM:-4094}
CPU=${CPU:-4}
SIZE=${SIZE:-40}
if [[ "$(id -u)" != "0" ]]; then
sudo="sudo"
fi
if ! which virt-install &> /dev/null; then
echo "Error: virt-install is not installed"
exit 1
fi
libvirt_dir=/var/lib/libvirt/images
img_name=$NAME
tmpdir=$(mktemp -d /tmp/virt-install_XXXXX)
tmp_ks_file=$tmpdir/$img_name.ks
function cleanup() {
set +e
read -p "brk: "
[[ -d "$tmpdir" ]] && rm -fr "$tmpdir"
local destroy_kvm=n
[[ -f "/etc/libvirt/qemu/$img_name.xml" ]] && read -p "Destroy libvirt VM (y/n)? " destroy_kvm
if [[ "$destroy_kvm" != n* ]]; then
virsh destroy $img_name
virsh undefine $img_name
virsh vol-delete $img_name.img --pool default
$sudo rm -f $libvirt_dir/$img_name.img
fi
}
trap cleanup EXIT
ruby <<DELIM__
require 'erb'
@password="$PASSWORD"
@name="$NAME"
@domain="example.com"
@github_access_token="$GITHUB_ACCESS_TOKEN"
@mirror="$MIRROR"
File.open('$tmp_ks_file', 'w') do |f|
f.puts ERB.new(File.open('$KICKSTART', 'rb').read, nil, '-').result()
end
DELIM__
tree=$MIRROR/Server/x86_64/os/
virt-install --connect=qemu:///system \
--network=bridge:$BRIDGE \
--initrd-inject=$tmp_ks_file \
--controller type=scsi,model=virtio-scsi \
--extra-args="ks=file:/$(basename $tmp_ks_file) console=tty0 console=ttyS0,115200" \
--name=$img_name \
--disk $libvirt_dir/$img_name.img,cache=none,format=qcow2,size=$SIZE,bus=scsi \
--ram $MEM \
--vcpus=$CPU \
--check-cpu \
--accelerate \
--hvm \
--location=$tree \
--nographics
echo "SUCCESS"
exit 0
......@@ -22,7 +22,7 @@ class TestKprobe(TestCase):
self.stats = self.prog.table("stats", Key, Leaf)
self.prog.attach_kprobe("sys_write", "sys_wr", 0, -1)
self.prog.attach_kprobe("sys_read", "sys_rd", 0, -1)
self.prog.attach_kprobe("htab_map_get_next_key", "sys_bpf")
self.prog.attach_kprobe("htab_map_get_next_key", "sys_bpf", 0, -1)
def test_trace1(self):
with open("/dev/null", "a") as f:
......
......@@ -10,7 +10,6 @@ class Ptr(Structure):
class Counters(Structure):
_fields_ = [("stat1", c_ulong)]
tracing = "/sys/kernel/debug/tracing"
class TestTracingEvent(TestCase):
def setUp(self):
self.prog = BPF("trace2", "trace2.b", "kprobe.b",
......
......@@ -25,6 +25,7 @@ function ns_run() {
sudo ip link add $ns.in type veth peer name $ns.out
sudo ip link set $ns.in netns $ns
sudo ip netns exec $ns ip link set $ns.in name eth0
sudo ip netns exec $ns tc qdisc add dev eth0 root prio
sudo ip netns exec $ns ip addr add dev eth0 172.16.1.2/24
sudo ip netns exec $ns ip link set eth0 up
sudo ip addr add dev $ns.out 172.16.1.1/24
......
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