program = BPF(
        text=r"""
#include <linux/cred.h>
#include <linux/sched.h>
#include <linux/user_namespace.h>
#include <uapi/linux/ptrace.h>

BPF_HASH(procs, u32, u32);


static inline int
__print_uid_map(struct pt_regs* ctx)
{
        struct task_struct* task;
        struct uid_gid_map* mapping;

        task = (struct task_struct*)bpf_get_current_task();
        mapping = &task->cred->user_ns->uid_map;

        if (mapping->nr_extents < 1) {
                return 0;
        }

        bpf_trace_printk("%d,%d,%d\n",
                         mapping->extent[0].first,
                         mapping->extent[0].lower_first,
                         mapping->extent[0].count);

        return 0;
}


int
kr__create_user_ns(struct pt_regs* ctx)
{
    bpf_trace_printk("create_user_ns\n");
    return __print_uid_map(ctx);
}


int
kr__proc_uid_map_write(struct pt_regs* ctx)
{
    u32 pid = bpf_get_current_pid_tgid() >> 32;
    procs.update(&pid, &pid);

    bpf_trace_printk("proc_uid_map\n");
    return __print_uid_map(ctx);
}

int
k__generic_permission(struct pt_regs* ctx)
{
        struct task_struct* task;
        struct uid_gid_map* mapping;
        u32 pid = bpf_get_current_pid_tgid() >> 32;

        u32 *pid_ptr = procs.lookup(&pid);
        if (pid_ptr == NULL) {
            return 0;
        }

        bpf_trace_printk("generic_permission\n");
        task = (struct task_struct*)bpf_get_current_task();
        bpf_trace_printk("fsuid=%d\n", task->cred->fsuid);

        return 0;
}
"""
)
 def test_gpl_helper_macro(self):
     b = BPF(text=self.gpl_only_text + self.license('GPL'))
     self.load_bpf_code(b)
 def test_proprietary_words_macro(self):
     b = BPF(text=self.proprietary_text + self.license('Proprietary license'))
     self.load_bpf_code(b)
Beispiel #4
0
 def setUp(self):
     b = BPF(text=text, debug=0)
     self.stats = b.get_table("stats")
     b.attach_kprobe(event="finish_task_switch", fn_name="count_sched")
 def test_proprietary_cflags_fail(self):
     b = BPF(text=self.proprietary_text, cflags=["-DBPF_LICENSE=Proprietary"])
     self.load_bpf_code(b)
#!/usr/bin/python
from bcc import BPF
import time
import socket
import struct
import sys
import imap, hosts
import geoip2

hosts.init()
device = "wlp8s0"
bpf = BPF(src_file="packet-capture.c")
fn = bpf.load_func("xdp_ip_counter", BPF.XDP)
bpf.attach_xdp(device, fn, 0)
counters = bpf.get_table("counters")

myPrivateIP = imap.getMyPrivateIP()
while True:
    print("watchdog")
    try:
        for k in counters.keys():
            val = counters[k].value
            if val:
                source = socket.inet_ntoa(struct.pack("!I", k.s_v4_addr))
                destination = socket.inet_ntoa(struct.pack("!I", k.d_v4_addr))
                if destination != myPrivateIP:
                    continue
                else:
                    try:
                        imap.addPeerToDB(source)
                    except geoip2.errors.AddressNotFoundError:
    struct data_t data = {.ts = now, .cpu = cpu, .len = len};
    events.perf_submit(ctx, &data, sizeof(data));

    return 0;
}
"""

# code substitutions
if debug or args.ebpf:
    print(bpf_text)
    if args.ebpf:
        exit()

# initialize BPF & perf_events
b = BPF(text=bpf_text)
# TODO: check for HW counters first and use if more accurate
b.attach_perf_event(ev_type=PerfType.SOFTWARE,
                    ev_config=PerfSWConfig.TASK_CLOCK,
                    fn_name="do_perf_event",
                    sample_period=0,
                    sample_freq=frequency)

if args.csv:
    if args.timestamp:
        print("TIME", end=",")
    print("TIMESTAMP_ns", end=",")
    print(",".join("CPU" + str(c) for c in range(ncpu)), end="")
    if args.fullcsv:
        print(",", end="")
        print(",".join("OFFSET_ns_CPU" + str(c) for c in range(ncpu)), end="")
Beispiel #8
0
from bcc import BPF

bpf_source = """
#include <uapi/linux/ptrace.h>

int do_sys_execve(struct pt_regs *ctx) {
  char comm[16];
  bpf_get_current_comm(&comm, sizeof(comm));
  bpf_trace_printk("executing program: %s \\n", comm);
  return 0;
}
"""

bpf = BPF(text=bpf_source)
execve_function = bpf.get_syscall_fnname("execve")
bpf.attach_kprobe(event=execve_function, fn_name="do_sys_execve")
bpf.trace_print()
Beispiel #9
0
    if (data_p) {
        data = *data_p;
        data.fun_ID  = FID_RECV_MSG;
        data.fun_ret = 1;
    }

    data.ts = bpf_ktime_get_ns();

    if (data.arg1 || data.arg2 || data.arg3 || data.arg4) {
        events.perf_submit(ctx, &data, sizeof(data));
    }
    return 0;
}
"""

bpf = BPF(text=intrucode)

LIBPATH="/home/hermes/workspace/opensplice/install/HDE/x86_64.linux-dev/lib/"

# Topic information recording
bpf.attach_uprobe(name="%slibdcpssac.so"%LIBPATH, sym="DDS_DomainParticipant_create_topic", fn_name="T_GetTopicName")
bpf.attach_uretprobe(name="%slibdcpssac.so"%LIBPATH, sym="DDS_DomainParticipant_create_topic", fn_name="T_MapTopic2TopicName")
bpf.attach_uprobe(name="%slibdcpssac.so"%LIBPATH, sym="DDS_Publisher_create_datawriter", fn_name="W_MapPID2Topic")
bpf.attach_uretprobe(name="%slibddskernel.so"%LIBPATH, sym="v_writerNew", fn_name="W_MapVWriter2TopicName")
bpf.attach_uretprobe(name="%slibdcpssac.so"%LIBPATH, sym="DDS_Publisher_create_datawriter", fn_name="W_MapWriter2TopicName")
bpf.attach_uprobe(name="%slibdcpssac.so"%LIBPATH, sym="DDS_Subscriber_create_datareader", fn_name="R_MapPID2Topic")
bpf.attach_uretprobe(name="%slibdcpssac.so"%LIBPATH, sym="DDS_Subscriber_create_datareader", fn_name="R_MapReader2TopicName")


# Write/Read Records
bpf.attach_uprobe(name="%slibdcpssac.so"%LIBPATH, sym= "DDS_DataWriter_write", fn_name="DDSWrite_Start")
Beispiel #10
0
        exit()
    stacks = sys.argv[2]
else:
    stacks = "1024"

# load BPF program
b = BPF(text="""
#include <uapi/linux/ptrace.h>

BPF_HASH(calls, int);
BPF_STACK_TRACE(stack_traces, """ + stacks + """);

int alloc_enter(struct pt_regs *ctx, size_t size) {
    int key = stack_traces.get_stackid(ctx, BPF_F_USER_STACK);
    if (key < 0)
        return 0;

    // could also use `calls.increment(key, size);`
    u64 zero = 0, *val;
    val = calls.lookup_or_try_init(&key, &zero);
    if (val) {
      (*val) += size;
    }
    return 0;
};
""")

b.attach_uprobe(name="c", sym="malloc", fn_name="alloc_enter", pid=pid)
print("Attaching to malloc in pid %d, Ctrl+C to quit." % pid)

# sleep until Ctrl-C
try:
Beispiel #11
0
b = BPF(text="""
#include <uapi/linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/ipv6.h>

BPF_TABLE(MAPTYPE, uint32_t, long, dropcnt, 256);

static inline int parse_ipv4(void *data, u64 nh_off, void *data_end) {
    struct iphdr *iph = data + nh_off;

    if ((void*)&iph[1] > data_end)
        return 0;
    return iph->protocol;
}

static inline int parse_ipv6(void *data, u64 nh_off, void *data_end) {
    struct ipv6hdr *ip6h = data + nh_off;

    if ((void*)&ip6h[1] > data_end)
        return 0;
    return ip6h->nexthdr;
}

int xdp_prog1(struct CTXTYPE *ctx) {

    void* data_end = (void*)(long)ctx->data_end;
    void* data = (void*)(long)ctx->data;

    struct ethhdr *eth = data;

    // drop packets
    int rc = RETURNCODE; // let pass XDP_PASS or redirect to tx via XDP_TX
    long *value;
    uint16_t h_proto;
    uint64_t nh_off = 0;
    uint32_t index;

    nh_off = sizeof(*eth);

    if (data + nh_off  > data_end)
        return rc;

    h_proto = eth->h_proto;

    // parse double vlans
    #pragma unroll
    for (int i=0; i<2; i++) {
        if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
            struct vlan_hdr *vhdr;

            vhdr = data + nh_off;
            nh_off += sizeof(struct vlan_hdr);
            if (data + nh_off > data_end)
                return rc;
                h_proto = vhdr->h_vlan_encapsulated_proto;
        }
    }

    if (h_proto == htons(ETH_P_IP))
        index = parse_ipv4(data, nh_off, data_end);
    else if (h_proto == htons(ETH_P_IPV6))
       index = parse_ipv6(data, nh_off, data_end);
    else
        index = 0;

    value = dropcnt.lookup(&index);
    if (value)
        __sync_fetch_and_add(value, 1);

    return rc;
}
""",
        cflags=[
            "-w",
            "-DRETURNCODE=%s" % ret,
            "-DCTXTYPE=%s" % ctxtype,
            "-DMAPTYPE=\"%s\"" % maptype
        ],
        device=offload_device)
Beispiel #12
0
#! /usr/bin/env python3

import ctypes as ct
import os, sys, signal, time, resource

from bcc import BPF
from bcc.libbcc import lib

if __name__ == "__main__":
    bpf = BPF(src_file="bigdata.c")

    def on_event(cpu, data, size):
        event = bpf['event'].event(data)
        print(f'{event}')

    bpf['event'].open_perf_buffer(on_event)

    while True:
        try:
            bpf.perf_buffer_poll(30)
            time.sleep(1)
        except KeyboardInterrupt:
            sys.exit(0)
Beispiel #13
0
        events.perf_submit(ctx, &data, sizeof(data));
#ifdef THRESHOLD
    }
#endif //THRESHOLD
    temp.delete(&pid);
    return 0;
};
""".replace("DEFINE_USDT", "#define USDT" if mode == "USDT" else "") \
   .replace("DEFINE_MYSQL56", "#define MYSQL56" if mode == "MYSQL56" else "") \
   .replace("DEFINE_MYSQL57", "#define MYSQL57" if mode == "MYSQL57" else "") \
   .replace("DEFINE_THRESHOLD",
            "#define THRESHOLD %d" % threshold_ns if threshold_ns > 0 else "")

if mode.startswith("MYSQL"):
    # Uprobes mode
    bpf = BPF(text=program)
    bpf.attach_uprobe(name=args.path, sym=mysql_func_name,
                      fn_name="query_start")
    bpf.attach_uretprobe(name=args.path, sym=mysql_func_name,
                         fn_name="query_end")
else:
    # USDT mode
    if not args.pids or len(args.pids) == 0:
        if args.db == "mysql":
            args.pids = map(int, subprocess.check_output(
                                            "pidof mysqld".split()).split())
        elif args.db == "postgres":
            args.pids = map(int, subprocess.check_output(
                                            "pidof postgres".split()).split())

    usdts = map(lambda pid: USDT(pid=pid), args.pids)
Beispiel #14
0
    int err_code = 0;
    bpf_usdt_readarg(6, ctx, &err_code);
    error_hist.increment(err_code);
    const char* addr = NULL;
    bpf_usdt_readarg(2, ctx, &addr);
    bpf_probe_read_str(out.name, sizeof(out.name), addr);
    out.error_code = err_code;
    failed.perf_submit(ctx, &out, sizeof(out));
    return 0;
}}
""".format(NUM_ERR_CODES=len(ERROR_CODES))

command_failed = USDT(pid=int(sys.argv[1]))
command_failed.enable_probe(probe="commandFail", fn_name="command_failed")

b = BPF(text = text, usdt_contexts=[command_failed])

command_to_errors = dict()
def print_event(cpu, data, size):
    event = b["failed"].event(data)
    event_name = str(event.name, 'utf-8')
    if event_name not in command_to_errors:
        command_to_errors[event_name] = dict()
    if event.error_code not in command_to_errors[event_name]:
        command_to_errors[event_name][event.error_code] = 0
    command_to_errors[event_name][event.error_code] += 1

b["failed"].open_perf_buffer(print_event)

print('listening until CTRL-C....')
print("{:<30} | Occurrences".format("Commands"))
Beispiel #15
0
 def test_exported_maps(self):
     b1 = BPF(text="""BPF_TABLE_PUBLIC("hash", int, int, table1, 10);""")
     b2 = BPF(text="""BPF_TABLE("extern", int, int, table1, 10);""")
Beispiel #16
0
#!/usr/bin/env python
from bcc import BPF

# sudo bpftrace -e 'kprobe:ext4_inode_csum { printf("trigger\n"); }'

BPF(text="""
#include <uapi/linux/ptrace.h>
int kprobe__ext4_inode_csum(struct pt_regs *ctx, struct inode *inode, struct ext4_inode *raw) {
    bpf_trace_printk("inode=%llx  raw=%llx  \\n", inode, raw);
    return 0;
}

int kretprobe__ext4_inode_csum(struct pt_regs *ctx) {
    unsigned long ret = PT_REGS_RC(ctx);
    bpf_trace_printk("ret: %llx\\n", ret);
    return 0;
}
""").trace_print()
Beispiel #17
0
 def test_syntax_error(self):
     with self.assertRaises(Exception):
         b = BPF(text="""int failure(void *ctx) { if (); return 0; }""")
Beispiel #18
0
from bcc import BPF, USDT

bpf_source = """
#include <uapi/linux/ptrace.h>
int trace_binary_exec(struct pt_regs *ctx) {
  u64 pid = bpf_get_current_pid_tgid();
  bpf_trace_printk("New hello_usdt process running with PID: %d", pid);
}
"""

usdt = USDT(path="./hello_usdt")
usdt.enable_probe(probe="probe-main", fn_name="trace_binary_exec")
bpf = BPF(text=bpf_source, usdt=usdt)
bpf.trace_print()
Beispiel #19
0
    def test_brb2(self):
        try:
            b = BPF(src_file=arg1, debug=0)
            self.pem_fn = b.load_func("pem", BPF.SCHED_CLS)
            self.pem_dest = b.get_table("pem_dest")
            self.pem_stats = b.get_table("pem_stats")

            # set up the topology
            self.set_default_const()
            (ns1_ipdb, self.ns1_eth_out,
             _) = sim._create_ns(self.ns1,
                                 ipaddr=self.vm1_ip + '/24',
                                 fn=self.pem_fn,
                                 action='drop',
                                 disable_ipv6=True)
            (ns2_ipdb, self.ns2_eth_out,
             _) = sim._create_ns(self.ns2,
                                 ipaddr=self.vm2_ip + '/24',
                                 fn=self.pem_fn,
                                 action='drop',
                                 disable_ipv6=True)
            ns1_ipdb.routes.add({
                'dst': self.vm2_rtr_mask,
                'gateway': self.vm1_rtr_ip
            }).commit()
            ns2_ipdb.routes.add({
                'dst': self.vm1_rtr_mask,
                'gateway': self.vm2_rtr_ip
            }).commit()

            (_, self.nsrtr_eth0_out,
             _) = sim._create_ns(self.ns_router,
                                 ipaddr=self.vm1_rtr_ip + '/24',
                                 disable_ipv6=True)
            (rt_ipdb, self.nsrtr_eth1_out,
             _) = sim._ns_add_ifc(self.ns_router,
                                  "eth1",
                                  "ns_router2",
                                  ipaddr=self.vm2_rtr_ip + '/24',
                                  disable_ipv6=True)
            # enable ip forwarding in router ns
            nsp = NSPopen(rt_ipdb.nl.netns,
                          ["sysctl", "-w", "net.ipv4.ip_forward=1"])
            nsp.wait()
            nsp.release()

            # for each VM connecting to pem, there will be a corresponding veth connecting to the bridge
            self.setup_br(self.br1, self.nsrtr_eth0_out.ifname,
                          self.veth_pem_2_br1, self.veth_br1_2_pem)
            self.setup_br(self.br2, self.nsrtr_eth1_out.ifname,
                          self.veth_pem_2_br2, self.veth_br2_2_pem)

            # load the program and configure maps
            self.config_maps()

            # ping
            nsp = NSPopen(ns1_ipdb.nl.netns, ["ping", self.vm2_ip, "-c", "2"])
            nsp.wait()
            nsp.release()
            # one arp request/reply, 2 icmp request/reply per VM, total 6 packets per VM, 12 packets total
            self.assertEqual(self.pem_stats[c_uint(0)].value, 12)

            nsp_server = NSPopen(ns2_ipdb.nl.netns, ["iperf", "-s", "-xSC"])
            sleep(1)
            nsp = NSPopen(ns1_ipdb.nl.netns,
                          ["iperf", "-c", self.vm2_ip, "-t", "1", "-xSC"])
            nsp.wait()
            nsp.release()
            nsp_server.kill()
            nsp_server.wait()
            nsp_server.release()

            nsp_server = NSPopen(ns2_ipdb.nl.netns, ["netserver", "-D"])
            sleep(1)
            nsp = NSPopen(
                ns1_ipdb.nl.netns,
                ["netperf", "-l", "1", "-H", self.vm2_ip, "--", "-m", "65160"])
            nsp.wait()
            nsp.release()
            nsp = NSPopen(
                ns1_ipdb.nl.netns,
                ["netperf", "-l", "1", "-H", self.vm2_ip, "-t", "TCP_RR"])
            nsp.wait()
            nsp.release()
            nsp_server.kill()
            nsp_server.wait()
            nsp_server.release()

        finally:
            if self.br1 in ipdb.interfaces:
                ipdb.interfaces[self.br1].remove().commit()
            if self.br2 in ipdb.interfaces:
                ipdb.interfaces[self.br2].remove().commit()
            if self.veth_pem_2_br1 in ipdb.interfaces:
                ipdb.interfaces[self.veth_pem_2_br1].remove().commit()
            if self.veth_pem_2_br2 in ipdb.interfaces:
                ipdb.interfaces[self.veth_pem_2_br2].remove().commit()
            sim.release()
            ipdb.release()
Beispiel #20
0
    if (valp == 0)
        return 0;       // missed start

    //bpf_probe_read_kernel(&data.comm, sizeof(data.comm), valp->comm);
    bpf_get_current_comm(&data.comm, sizeof(data.comm));
    data.pid = valp->pid;
    data.order = valp->order;
    data.delta = tsp - valp->ts;
    data.ts = valp->ts;
    events.perf_submit(ctx, &data, sizeof(data));
    start.delete(&pid);
    return 0;
}
"""

b = BPF(text=prog)

#b.attach_kprobe(event="huge_pte_alloc", fn_name="trace_hugepte")
b.attach_kprobe(event="__alloc_pages_nodemask", fn_name="do_entry")
b.attach_kretprobe(event="__alloc_pages_nodemask", fn_name="do_return")
# b.detach_kprobe(event="__alloc_pages_nodemask")
# b.detach_kretprobe(event="__alloc_pages_nodemask")


time = [ ]
pid = [ ]
comm = [ ]
latns = [ ]
host = [ ]
tsp = [ ]
order = [ ]
Beispiel #21
0
        for addr in stack[1:args.stacks]:
            print("%40s" % b.ksym(addr, show_offset=True))


if args.tid:  # TID trumps PID
    program = program.replace('FILTER',
                              'if (tid != %s) { return 0; }' % args.tid)
elif args.pid:
    program = program.replace('FILTER',
                              'if (pid != %s) { return 0; }' % args.pid)
else:
    program = program.replace('FILTER', '')

program = program.replace('STACK_STORAGE_SIZE', str(args.stack_storage_size))

b = BPF(text=program)

b.attach_kprobe(event="mutex_unlock", fn_name="mutex_unlock_enter")
b.attach_kretprobe(event="mutex_lock", fn_name="mutex_lock_return")
b.attach_kprobe(event="mutex_lock", fn_name="mutex_lock_enter")

enabled = b.get_table("enabled")

stack_traces = b.get_table("stack_traces")
aq_counts = b.get_table("aq_report_count")
aq_maxs = b.get_table("aq_report_max")
aq_totals = b.get_table("aq_report_total")

hl_counts = b.get_table("hl_report_count")
hl_maxs = b.get_table("hl_report_max")
hl_totals = b.get_table("hl_report_total")
Beispiel #22
0
from bcc import BPF
BPF(text='''
	int kprobe__sys_clone(void *ctx) { 
		bpf_trace_printk("%llu\\n", bpf_get_smp_processor_id()); 
		return 0; 
	}''').trace_print()

Beispiel #23
0
bpf_text = bpf_text.replace("FILTER_STRING", this_filter)
if this_filter:
    bpf_text = bpf_text.replace(
        "FILTER", "if (!filter(start_data.input)) { return 0; }")
else:
    bpf_text = bpf_text.replace("FILTER", "")

# Create USDT context
print("Attaching probes to pid %d" % this_pid)
usdt_ctx = USDT(pid=this_pid)
usdt_ctx.enable_probe(probe="operation_start", fn_name="trace_operation_start")
usdt_ctx.enable_probe(probe="operation_end", fn_name="trace_operation_end")

# Create BPF context, load BPF program
bpf_ctx = BPF(text=bpf_text, usdt_contexts=[usdt_ctx], debug=debugLevel)


# Define latency event and print function
class OperationEventData(ct.Structure):
    _fields_ = [("operation_id", ct.c_ulonglong), ("input", ct.c_char * 64),
                ("output", ct.c_char * 64), ("start", ct.c_ulonglong),
                ("end", ct.c_ulonglong), ("duration", ct.c_ulonglong)]


start = 0


def print_event(cpu, data, size):
    global start
    event = ct.cast(data, ct.POINTER(OperationEventData)).contents
Beispiel #24
0
def bench_redis(repeat=3, n=1000000):
    # type: (int, int) -> pandas.DataFrame

    def read_result(name, file):
        # type: (str, Optional[IO[Any]]) -> pandas.DataFrame
        df = pandas.read_csv(file, names=["Type", "Req/s"])
        df["Name"] = name
        return df

    bench_cmd = [
        "redis-benchmark",
        "-r",
        "100000",
        "-t",
        "set,lpush",
        "-n",
        str(n),
        "--csv",
        "-p",
    ]

    init_port = 10000

    results = []

    syscalls, bpf_prog = read_syscall()

    with open(os.devnull, "w") as fnull:
        for i in range(repeat):
            print("Record {}th performance without bpf".format(i))

            while check_port_inuse(init_port):
                init_port += 1

            serv = subprocess.Popen(server_cmd + [str(init_port)],
                                    stdout=fnull)
            sleep(1)  # for setup
            bench = subprocess.Popen(bench_cmd + [str(init_port)],
                                     stdout=subprocess.PIPE)
            bench.wait()
            serv.terminate()
            results.append(read_result("no-bpf", bench.stdout))

        b = BPF(text=bpf_prog)
        for sysc in syscalls:
            try:
                b.attach_kprobe(event=sysc, fn_name="dump")
                b.attach_kretprobe(event=sysc, fn_name="dump")
            except Exception as e:
                print(str(e) + ", syscall: {}".format(sysc))

        for i in range(repeat):
            print("Record {}th performance with bpf".format(i))

            while check_port_inuse(init_port):
                init_port += 1

            serv = subprocess.Popen(server_cmd + [str(init_port)],
                                    stdout=fnull)
            sleep(1)  # for setup
            bench = subprocess.Popen(bench_cmd + [str(init_port)],
                                     stdout=subprocess.PIPE)
            bench.wait()
            serv.terminate()
            results.append(read_result("bpf", bench.stdout))

    df = pandas.concat(results)
    path = os.path.join(os.path.dirname(__file__), "results", "syscall.tsv")
    print("wrote %s" % path)
    df.to_csv(path, sep="\t")
 def test_default(self):
     b = BPF(text=self.gpl_only_text)
     self.load_bpf_code(b)
Beispiel #26
0
    def test_char_array_probe(self):
        BPF(text="""#include <linux/blkdev.h>
int kprobe__blk_update_request(struct pt_regs *ctx, struct request *req) {
    bpf_trace_printk("%s\\n", req->rq_disk->disk_name);
    return 0;
}""")
 def test_gpl_compatible_macro(self):
     b = BPF(text=self.gpl_only_text + self.license('Dual BSD/GPL'))
     self.load_bpf_code(b)
Beispiel #28
0
 def test_complex(self):
     b = BPF(src_file="test_clang_complex.c", debug=0)
     fn = b.load_func("handle_packet", BPF.SCHED_CLS)
 def test_cflags_fail(self):
     b = BPF(text=self.gpl_only_text, cflags=["-DBPF_LICENSE=GPL"])
     self.load_bpf_code(b)
Beispiel #30
0
def main():
    #
    # Don't like these globals, but ctx passing does not seem to work with the
    # existing open_ring_buffer() API :(
    #
    global b
    global options

    #
    # Argument parsing
    #
    parser = argparse.ArgumentParser()

    parser.add_argument("--buffer-page-count",
                        help="Number of BPF ring buffer pages, default 1024",
                        type=int,
                        default=1024,
                        metavar="NUMBER")
    parser.add_argument("-D",
                        "--debug",
                        help="Enable eBPF debugging",
                        type=int,
                        const=0x3f,
                        default=0,
                        nargs='?')
    parser.add_argument('-d',
                        '--packet-decode',
                        help='Display packet content in selected mode, '
                        'default none',
                        choices=['none', 'hex', 'decode'],
                        default='none')
    parser.add_argument("-f",
                        "--flow-key-size",
                        help="Set maximum flow key size to capture, "
                        "default 64",
                        type=buffer_size_type,
                        default=64,
                        metavar="[64-2048]")
    parser.add_argument('-k',
                        '--flow-key-decode',
                        help='Display flow-key content in selected mode, '
                        'default none',
                        choices=['none', 'hex', 'nlraw'],
                        default='none')
    parser.add_argument("-p",
                        "--pid",
                        metavar="VSWITCHD_PID",
                        help="ovs-vswitch's PID",
                        type=int,
                        default=None)
    parser.add_argument("-s",
                        "--packet-size",
                        help="Set maximum packet size to capture, "
                        "default 64",
                        type=buffer_size_type,
                        default=64,
                        metavar="[64-2048]")
    parser.add_argument("-w",
                        "--pcap",
                        metavar="PCAP_FILE",
                        help="Write upcall packets to specified pcap file.",
                        type=str,
                        default=None)

    options = parser.parse_args()

    #
    # Find the PID of the ovs-vswitchd daemon if not specified.
    #
    if options.pid is None:
        for proc in psutil.process_iter():
            if 'ovs-vswitchd' in proc.name():
                if options.pid is not None:
                    print("ERROR: Multiple ovs-vswitchd daemons running, "
                          "use the -p option!")
                    sys.exit(-1)

                options.pid = proc.pid

    #
    # Error checking on input parameters
    #
    if options.pid is None:
        print("ERROR: Failed to find ovs-vswitchd's PID!")
        sys.exit(-1)

    if options.pcap is not None:
        if exists(options.pcap):
            print("ERROR: Destination capture file \"{}\" already exists!".
                  format(options.pcap))
            sys.exit(-1)

    options.buffer_page_count = next_power_of_two(options.buffer_page_count)

    #
    # Attach the usdt probe
    #
    u = USDT(pid=int(options.pid))
    try:
        u.enable_probe(probe="recv_upcall", fn_name="do_trace")
    except USDTException as e:
        print("ERROR: {}"
              "ovs-vswitchd!".format(
                  (re.sub('^', ' ' * 7, str(e),
                          flags=re.MULTILINE)).strip().replace(
                              "--with-dtrace or --enable-dtrace",
                              "--enable-usdt-probes")))
        sys.exit(-1)

    #
    # Uncomment to see how arguments are decoded.
    #   print(u.get_text())
    #

    #
    # Attach probe to running process
    #
    source = ebpf_source.replace("<MAX_PACKET_VAL>", str(options.packet_size))
    source = source.replace("<MAX_KEY_VAL>", str(options.flow_key_size))
    source = source.replace("<BUFFER_PAGE_CNT>",
                            str(options.buffer_page_count))

    b = BPF(text=source, usdt_contexts=[u], debug=options.debug)

    #
    # Print header
    #
    print("{:<18} {:<4} {:<16} {:<10} {:<32} {:<4} {:<10} {:<10}".format(
        "TIME", "CPU", "COMM", "PID", "DPIF_NAME", "TYPE", "PKT_LEN",
        "FLOW_KEY_LEN"))

    #
    # Dump out all events
    #
    b['events'].open_ring_buffer(print_event)
    while 1:
        try:
            b.ring_buffer_poll()
            time.sleep(0.5)
        except KeyboardInterrupt:
            break

    dropcnt = b.get_table("dropcnt")
    for k in dropcnt.keys():
        count = dropcnt.sum(k).value
        if k.value == 0 and count > 0:
            print("\nWARNING: Not all upcalls were captured, {} were dropped!"
                  "\n         Increase the BPF ring buffer size with the "
                  "--buffer-page-count option.".format(count))