mirror_iproute2/configure
Daniel Borkmann 11c39b5e98 tc: add eBPF support to f_bpf
This work adds the tc frontend for kernel commit e2e9b6541dd4 ("cls_bpf:
add initial eBPF support for programmable classifiers").

A C-like classifier program (f.e. see e2e9b6541dd4) is being compiled via
LLVM's eBPF backend into an ELF file, that is then being passed to tc. tc
then loads, if any, eBPF maps and eBPF opcodes (with fixed-up eBPF map file
descriptors) out of its dedicated sections, and via bpf(2) into the kernel
and then the resulting fd via netlink down to cls_bpf. cls_bpf allows for
annotations, currently, I've used the file name for that, so that the user
can easily identify his filter when dumping configurations back.

Example usage:

  clang -O2 -emit-llvm -c cls.c -o - | llc -march=bpf -filetype=obj -o cls.o
  tc filter add dev em1 parent 1: bpf run object-file cls.o classid x:y

  tc filter show dev em1 [...]
  filter parent 1: protocol all pref 49152 bpf handle 0x1 flowid x:y cls.o

I placed the parser bits derived from Alexei's kernel sample, into tc_bpf.c
as my next step is to also add the same support for BPF action, so we can
have a fully fledged eBPF classifier and action in tc.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
2015-03-24 15:45:23 -07:00

337 lines
6.5 KiB
Bash
Executable File

#! /bin/bash
# This is not an autoconf generated configure
#
INCLUDE=${1:-"$PWD/include"}
# Make a temp directory in build tree.
TMPDIR=$(mktemp -d config.XXXXXX)
trap 'status=$?; rm -rf $TMPDIR; exit $status' EXIT HUP INT QUIT TERM
check_prog()
{
echo -n "$2"
command -v $1 >/dev/null 2>&1 && (echo "$3:=y" >> Config; echo "yes") || (echo "no"; return 1)
}
check_docs()
{
if check_prog latex " latex: " HAVE_LATEX; then
check_prog pdflatex " pdflatex: " HAVE_PDFLATEX || echo " WARNING: no PDF docs can be built from LaTeX files"
check_prog sgml2latex " sgml2latex: " HAVE_SGML2LATEX || echo " WARNING: no LaTeX files can be build from SGML files"
else
echo " WARNING: no docs can be built from LaTeX files"
fi
check_prog sgml2html " sgml2html: " HAVE_SGML2HTML || echo " WARNING: no HTML docs can be built from SGML"
}
check_toolchain()
{
: ${PKG_CONFIG:=pkg-config}
: ${AR=ar}
: ${CC=gcc}
echo "PKG_CONFIG:=${PKG_CONFIG}" >>Config
echo "AR:=${AR}" >>Config
echo "CC:=${CC}" >>Config
}
check_atm()
{
cat >$TMPDIR/atmtest.c <<EOF
#include <atm.h>
int main(int argc, char **argv) {
struct atm_qos qos;
(void) text2qos("aal5,ubr:sdu=9180,rx:none",&qos,0);
return 0;
}
EOF
$CC -I$INCLUDE -o $TMPDIR/atmtest $TMPDIR/atmtest.c -latm >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo "TC_CONFIG_ATM:=y" >>Config
echo yes
else
echo no
fi
rm -f $TMPDIR/atmtest.c $TMPDIR/atmtest
}
check_xt()
{
#check if we have xtables from iptables >= 1.4.5.
cat >$TMPDIR/ipttest.c <<EOF
#include <xtables.h>
#include <linux/netfilter.h>
static struct xtables_globals test_globals = {
.option_offset = 0,
.program_name = "tc-ipt",
.program_version = XTABLES_VERSION,
.orig_opts = NULL,
.opts = NULL,
.exit_err = NULL,
};
int main(int argc, char **argv)
{
xtables_init_all(&test_globals, NFPROTO_IPV4);
return 0;
}
EOF
if $CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL \
$(${PKG_CONFIG} xtables --cflags --libs) -ldl >/dev/null 2>&1
then
echo "TC_CONFIG_XT:=y" >>Config
echo "using xtables"
fi
rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest
}
check_xt_old()
{
# bail if previous XT checks has already succeded.
if grep -q TC_CONFIG_XT Config
then
return
fi
#check if we dont need our internal header ..
cat >$TMPDIR/ipttest.c <<EOF
#include <xtables.h>
char *lib_dir;
unsigned int global_option_offset = 0;
const char *program_version = XTABLES_VERSION;
const char *program_name = "tc-ipt";
struct afinfo afinfo = {
.libprefix = "libxt_",
};
void exit_error(enum exittype status, const char *msg, ...)
{
}
int main(int argc, char **argv) {
return 0;
}
EOF
$CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL -ldl >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo "TC_CONFIG_XT_OLD:=y" >>Config
echo "using old xtables (no need for xt-internal.h)"
fi
rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest
}
check_xt_old_internal_h()
{
# bail if previous XT checks has already succeded.
if grep -q TC_CONFIG_XT Config
then
return
fi
#check if we need our own internal.h
cat >$TMPDIR/ipttest.c <<EOF
#include <xtables.h>
#include "xt-internal.h"
char *lib_dir;
unsigned int global_option_offset = 0;
const char *program_version = XTABLES_VERSION;
const char *program_name = "tc-ipt";
struct afinfo afinfo = {
.libprefix = "libxt_",
};
void exit_error(enum exittype status, const char *msg, ...)
{
}
int main(int argc, char **argv) {
return 0;
}
EOF
$CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL -ldl >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo "using old xtables with xt-internal.h"
echo "TC_CONFIG_XT_OLD_H:=y" >>Config
fi
rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest
}
check_ipt()
{
if ! grep TC_CONFIG_XT Config > /dev/null
then
echo "using iptables"
fi
}
check_ipt_lib_dir()
{
IPT_LIB_DIR=$(${PKG_CONFIG} --variable=xtlibdir xtables)
if [ -n "$IPT_LIB_DIR" ]; then
echo $IPT_LIB_DIR
echo "IPT_LIB_DIR:=$IPT_LIB_DIR" >> Config
return
fi
for dir in /lib /usr/lib /usr/local/lib
do
for file in $dir/{xtables,iptables}/lib*t_*so ; do
if [ -f $file ]; then
echo ${file%/*}
echo "IPT_LIB_DIR:=${file%/*}" >> Config
return
fi
done
done
echo "not found!"
}
check_setns()
{
cat >$TMPDIR/setnstest.c <<EOF
#include <sched.h>
int main(int argc, char **argv)
{
(void)setns(0,0);
return 0;
}
EOF
$CC -I$INCLUDE -o $TMPDIR/setnstest $TMPDIR/setnstest.c >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo "IP_CONFIG_SETNS:=y" >>Config
echo "yes"
else
echo "no"
fi
rm -f $TMPDIR/setnstest.c $TMPDIR/setnstest
}
check_netnsid()
{
cat >$TMPDIR/netnsid.c <<EOF
#include <linux/rtnetlink.h>
int test_def = RTM_GETNSID;
EOF
$CC -c $TMPDIR/netnsid.c >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo "IP_CONFIG_NETNSID:=y" >> Config
echo "yes"
else
echo "no"
fi
rm -f $TMPDIR/netnsid.c $TMPDIR/netnsid.o
}
check_ipset()
{
cat >$TMPDIR/ipsettest.c <<EOF
#include <linux/netfilter/ipset/ip_set.h>
#ifndef IP_SET_INVALID
#define IPSET_DIM_MAX 3
typedef unsigned short ip_set_id_t;
#endif
#include <linux/netfilter/xt_set.h>
struct xt_set_info info;
#if IPSET_PROTOCOL == 6
int main(void)
{
return IPSET_MAXNAMELEN;
}
#else
#error unknown ipset version
#endif
EOF
if $CC -I$INCLUDE -o $TMPDIR/ipsettest $TMPDIR/ipsettest.c >/dev/null 2>&1
then
echo "TC_CONFIG_IPSET:=y" >>Config
echo "yes"
else
echo "no"
fi
rm -f $TMPDIR/ipsettest.c $TMPDIR/ipsettest
}
check_elf()
{
cat >$TMPDIR/elftest.c <<EOF
#include <libelf.h>
#include <gelf.h>
int main(void)
{
Elf_Scn *scn;
GElf_Shdr shdr;
return elf_version(EV_CURRENT);
}
EOF
if $CC -I$INCLUDE -o $TMPDIR/elftest $TMPDIR/elftest.c -lelf >/dev/null 2>&1
then
echo "TC_CONFIG_ELF:=y" >>Config
echo "yes"
else
echo "no"
fi
rm -f $TMPDIR/elftest.c $TMPDIR/elftest
}
check_selinux()
# SELinux is a compile time option in the ss utility
{
if ${PKG_CONFIG} libselinux --exists
then
echo "HAVE_SELINUX:=y" >>Config
echo "yes"
else
echo "no"
fi
}
echo "# Generated config based on" $INCLUDE >Config
check_toolchain
echo "TC schedulers"
echo -n " ATM "
check_atm
echo -n " IPT "
check_xt
check_xt_old
check_xt_old_internal_h
check_ipt
echo -n " IPSET "
check_ipset
echo -n -e "\niptables modules directory: "
check_ipt_lib_dir
echo -n "libc has setns: "
check_setns
echo -n "netns has peer id suport: "
check_netnsid
echo -n "SELinux support: "
check_selinux
echo -n "ELF support: "
check_elf
echo -e "\nDocs"
check_docs