def setUp(self): b = BPF(arg1, arg2, debug=0) fn = b.load_func("on_packet", BPF.SCHED_CLS) ip = IPRoute() ifindex = ip.link_lookup(ifname="eth0")[0] # set up a network to change the flow: # outside | inside # 172.16.1.1 - 172.16.1.2 | 192.168.1.1 - 192.16.1.2 ip.addr("del", index=ifindex, address="172.16.1.2", mask=24) ip.addr("add", index=ifindex, address="192.168.1.2", mask=24) # add an ingress and egress qdisc ip.tc("add", "ingress", ifindex, "ffff:") ip.tc("add", "sfq", ifindex, "1:") # add same program to both ingress/egress, so pkt is translated in both directions ip.tc("add-filter", "bpf", ifindex, ":1", fd=fn.fd, name=fn.name, parent="ffff:", action="ok", classid=1) ip.tc("add-filter", "bpf", ifindex, ":2", fd=fn.fd, name=fn.name, parent="1:", action="ok", classid=1) self.xlate = b.get_table("xlate")
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()
def test_probe_read2(self): text = """ #include <linux/sched.h> #include <uapi/linux/ptrace.h> int count_foo(struct pt_regs *ctx, unsigned long a, unsigned long b) { return (a != b); } """ b = BPF(text=text, debug=0) fn = b.load_func("count_foo", BPF.KPROBE)
def setUp(self): b = BPF(arg1, arg2, debug=0) fn1 = b.load_func("probe_blk_start_request", BPF.KPROBE) fn2 = b.load_func("probe_blk_update_request", BPF.KPROBE) self.latency = b.get_table("latency", c_uint, c_ulong) BPF.attach_kprobe(fn1, "blk_start_request", -1, 0) BPF.attach_kprobe(fn2, "blk_update_request", -1, 0)
def test_probe_read1(self): text = """ #include <linux/sched.h> #include <uapi/linux/ptrace.h> int count_sched(struct pt_regs *ctx, struct task_struct *prev) { pid_t p = prev->pid; return (p != -1); } """ b = BPF(text=text, debug=0) fn = b.load_func("count_sched", BPF.KPROBE)
def test_blk_start_request(self): text = """ #include <linux/blkdev.h> #include <uapi/linux/ptrace.h> int do_request(struct pt_regs *ctx, int req) { bpf_trace_printk("req ptr: 0x%x\\n", req); return 0; } """ b = BPF(text=text, debug=0) fn = b.load_func("do_request", BPF.KPROBE)
def test_printk(self): text = """ #include <bcc/proto.h> int handle_packet(void *ctx) { u8 *cursor = 0; struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); bpf_trace_printk("ethernet->dst = %llx, ethernet->src = %llx\\n", ethernet->dst, ethernet->src); return 0; } """ b = BPF(text=text, debug=0) fn = b.load_func("handle_packet", BPF.SCHED_CLS)
def test_sscanf(self): text = """ BPF_TABLE("hash", int, struct { u64 a; u64 b; u64 c:36; u64 d:28; struct { u32 a; u32 b; } s; }, stats, 10); int foo(void *ctx) { return 0; } """ b = BPF(text=text, debug=0) fn = b.load_func("foo", BPF.KPROBE) t = b.get_table("stats") s1 = t.key_sprintf(t.Key(2)) self.assertEqual(s1, b"0x2") s2 = t.leaf_sprintf(t.Leaf(2, 3, 4, 1, (5, 6))) l = t.leaf_scanf(s2) self.assertEqual(l.a, 2) self.assertEqual(l.b, 3) self.assertEqual(l.c, 4) self.assertEqual(l.d, 1) self.assertEqual(l.s.a, 5) self.assertEqual(l.s.b, 6)
def test_iosnoop(self): text = """ #include <linux/blkdev.h> #include <uapi/linux/ptrace.h> struct key_t { struct request *req; }; BPF_TABLE("hash", struct key_t, u64, start, 1024); int do_request(struct pt_regs *ctx, struct request *req) { struct key_t key = {}; bpf_trace_printk("traced start %d\\n", req->__data_len); return 0; } """ b = BPF(text=text, debug=0) fn = b.load_func("do_request", BPF.KPROBE)
def __init__(self, login_info): # bind the h3c client to the EAP protocol try: self.client = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETHERTYPE_PAE)) self.client.bind((login_info['ethernet_interface'], ETHERTYPE_PAE)) # get local ethernet card address self.mac_addr = self.client.getsockname()[4] except AttributeError: self.client = BPF(ETHERTYPE_PAE) self.client.bind(login_info['ethernet_interface']) self.mac_addr = self.client.get_mac_address( login_info['ethernet_interface']) self.ethernet_header = get_ethernet_header(self.mac_addr, PAE_GROUP_ADDR, ETHERTYPE_PAE) self.has_sent_logoff = False self.login_info = login_info self.version_info = '\x06\x07bjQ7SE8BZ3MqHhs3clMregcDY3Y=\x20\x20'
def setUp(self): b = BPF(arg1, arg2, debug=0) self.latency = b.get_table("latency", c_uint, c_ulong) b.attach_kprobe(event="blk_start_request", fn_name="probe_blk_start_request", pid=-1, cpu=0) b.attach_kprobe(event="blk_update_request", fn_name="probe_blk_update_request", pid=-1, cpu=0)
class TestKprobeRgx(TestCase): def setUp(self): self.b = BPF( text=""" typedef struct { int idx; } Key; typedef struct { u64 val; } Val; BPF_TABLE("array", Key, Val, stats, 3); int hello(void *ctx) { stats.lookup_or_init(&(Key){1}, &(Val){0})->val++; return 0; } int goodbye(void *ctx) { stats.lookup_or_init(&(Key){2}, &(Val){0})->val++; return 0; } """ ) self.b.attach_kprobe(event_re="^SyS_bp.*", fn_name="hello") self.b.attach_kretprobe(event_re="^SyS_bp.*", fn_name="goodbye") def test_send1(self): k1 = self.b["stats"].Key(1) k2 = self.b["stats"].Key(2) self.assertEqual(self.b["stats"][k1].val, self.b["stats"][k2].val + 1)
def __init__(self, login_info): # bind the h3c client to the EAP protocol try: self.client = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETHERTYPE_PAE)) self.client.bind((login_info['ethernet_interface'], ETHERTYPE_PAE)) # get local ethernet card address self.mac_addr = self.client.getsockname()[4] except AttributeError: self.client = BPF(ETHERTYPE_PAE) self.client.bind(login_info['ethernet_interface']) self.mac_addr = self.client.get_mac_address(login_info['ethernet_interface']) self.ethernet_header = get_ethernet_header(self.mac_addr, PAE_GROUP_ADDR, ETHERTYPE_PAE) self.has_sent_logoff = False self.login_info = login_info self.version_info = '\x06\x07bjQ7SE8BZ3MqHhs3clMregcDY3Y=\x20\x20'
def setUp(self): b = BPF(src_file=arg1, debug=0) ether_fn = b.load_func("parse_ether", BPF.SCHED_CLS) arp_fn = b.load_func("parse_arp", BPF.SCHED_CLS) ip_fn = b.load_func("parse_ip", BPF.SCHED_CLS) eop_fn = b.load_func("eop", BPF.SCHED_CLS) ip = IPRoute() ifindex = ip.link_lookup(ifname="eth0")[0] ip.tc("add", "sfq", ifindex, "1:") ip.tc("add-filter", "bpf", ifindex, ":1", fd=ether_fn.fd, name=ether_fn.name, parent="1:", action="ok", classid=1) self.jump = b.get_table("jump", c_int, c_int) self.jump[c_int(S_ARP)] = c_int(arp_fn.fd) self.jump[c_int(S_IP)] = c_int(ip_fn.fd) self.jump[c_int(S_EOP)] = c_int(eop_fn.fd) self.stats = b.get_table("stats", c_int, c_ulonglong)
def setUp(self): self.b = BPF( text=""" typedef struct { int idx; } Key; typedef struct { u64 val; } Val; BPF_TABLE("array", Key, Val, stats, 3); int hello(void *ctx) { stats.lookup_or_init(&(Key){1}, &(Val){0})->val++; return 0; } int goodbye(void *ctx) { stats.lookup_or_init(&(Key){2}, &(Val){0})->val++; return 0; } """ ) self.b.attach_kprobe(event_re="^SyS_bp.*", fn_name="hello") self.b.attach_kretprobe(event_re="^SyS_bp.*", fn_name="goodbye")
# Licensed under the Apache License, Version 2.0 (the "License") from sys import argv from bpf import BPF from builtins import input from ctypes import c_int, c_uint from http.server import HTTPServer, SimpleHTTPRequestHandler import json from netaddr import EUI, IPAddress from pyroute2 import IPRoute, NetNS, IPDB, NSPopen from socket import htons, AF_INET from threading import Thread host_id = int(argv[1]) b = BPF(src_file="tunnel.c") ingress_fn = b.load_func("handle_ingress", BPF.SCHED_CLS) egress_fn = b.load_func("handle_egress", BPF.SCHED_CLS) mac2host = b.get_table("mac2host") vni2if = b.get_table("vni2if") conf = b.get_table("conf") ipr = IPRoute() ipdb = IPDB(nl=ipr) ifc = ipdb.interfaces.eth0 mcast = IPAddress("239.1.1.1") # ifcs to cleanup at the end ifc_gc = []
from bpf import BPF from builtins import input from pyroute2 import IPRoute, NetNS, IPDB, NSPopen from random import shuffle from time import sleep from simulation import Simulation import sys ipr = IPRoute() ipdb = IPDB(nl=ipr) num_clients = 3 num_vlans = 16 # load the bpf program b = BPF(src_file="vlan_learning.c", debug=0) phys_fn = b.load_func("handle_phys2virt", BPF.SCHED_CLS) virt_fn = b.load_func("handle_virt2phys", BPF.SCHED_CLS) ingress = b.get_table("ingress") egress = b.get_table("egress") class VlanSimulation(Simulation): def __init__(self, ipdb): super(VlanSimulation, self).__init__(ipdb) def start(self): # start identical workers each in a namespace for i in range(0, num_clients): httpmod = ("SimpleHTTPServer" if sys.version_info[0] < 3 else "http.server")
#!/usr/bin/env python # Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") from bpf import BPF from pyroute2 import IPRoute ipr = IPRoute() text = """ int hello(struct __sk_buff *skb) { return 1; } """ try: b = BPF(text=text, debug=0) fn = b.load_func("hello", BPF.SCHED_CLS) ipr.link_create(ifname="t1a", kind="veth", peer="t1b") idx = ipr.link_lookup(ifname="t1a")[0] ipr.tc("add", "ingress", idx, "ffff:") ipr.tc("add-filter", "bpf", idx, ":1", fd=fn.fd, name=fn.name, parent="ffff:", action="ok", classid=1) ipr.tc("add", "sfq", idx, "1:") ipr.tc("add-filter", "bpf", idx, ":1", fd=fn.fd, name=fn.name, parent="1:", action="ok", classid=1) finally: if "idx" in locals(): ipr.link_remove(idx)
#!/usr/bin/env python # Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") # run in project examples directory with: # sudo ./hello_world.py" from bpf import BPF from subprocess import call prog = """ int hello(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }; """ b = BPF(text=prog) fn = b.load_func("hello", BPF.KPROBE) BPF.attach_kprobe(fn, "sys_clone") try: call(["cat", "/sys/kernel/debug/tracing/trace_pipe"]) except KeyboardInterrupt: pass
def setUp(self): b = BPF(arg1, arg2, debug=0) fn = b.load_func("on_packet", BPF.SOCKET_FILTER) BPF.attach_raw_socket(fn, "eth0") self.stats = b.get_table("stats", Key, Leaf)
from bpf import BPF from builtins import input from ctypes import c_int, c_uint from http.server import HTTPServer, SimpleHTTPRequestHandler import json from netaddr import EUI, IPAddress from pyroute2 import IPRoute, NetNS, IPDB, NSPopen from socket import htons, AF_INET from threading import Thread from subprocess import call, Popen, PIPE num_hosts = int(argv[1]) host_id = int(argv[2]) dhcp = int(argv[3]) b = BPF(src_file="tunnel_mesh.c") ingress_fn = b.load_func("handle_ingress", BPF.SCHED_CLS) egress_fn = b.load_func("handle_egress", BPF.SCHED_CLS) tunkey2if = b.get_table("tunkey2if") if2tunkey = b.get_table("if2tunkey") conf = b.get_table("conf") ipr = IPRoute() ipdb = IPDB(nl=ipr) ifc = ipdb.interfaces.eth0 # ifcs to cleanup at the end ifc_gc = [] # dhcp server and client processes
# # syncsnoop.py Trace sync() syscall. # For Linux, uses BCC, eBPF. Embedded C. # # Written as a basic example of BCC trace & reformat. See hello_world.py # for a BCC trace with default output example. # # 13-Aug-2015 Brendan Gregg Created this. from bpf import BPF import sys # load BPF program b = BPF(text = """ int do_sync(void *ctx) { bpf_trace_printk("sync()\\n"); return 0; }; """) BPF.attach_kprobe(b.load_func("do_sync", BPF.KPROBE), "sys_sync") # header print "%-18s %s" % ("TIME(s)", "CALL") # open trace pipe try: trace = open("/sys/kernel/debug/tracing/trace_pipe", "r") except: print >> sys.stderr, "ERROR: opening trace_pipe" exit(1) # format output
def setUp(self): b = BPF(text=text, debug=0) self.stats = b.get_table("stats") b.attach_kprobe(event="schedule+50", fn_name="count_sched", pid=0, cpu=-1)
def setUp(self): b = BPF(arg1, arg2, debug=0) self.stats = b.get_table("stats", Key, Leaf) b.attach_kprobe(event="sys_write", fn_name="sys_wr", pid=0, cpu=-1) b.attach_kprobe(event="sys_read", fn_name="sys_rd", pid=0, cpu=-1) b.attach_kprobe(event="htab_map_get_next_key", fn_name="sys_rd", pid=0, cpu=-1)
#!/usr/bin/python # Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") from bpf import BPF from time import sleep b = BPF(src_file="task_switch.c") fn = b.load_func("count_sched", BPF.KPROBE) stats = b.get_table("stats") BPF.attach_kprobe(fn, "finish_task_switch") # generate many schedule events for i in range(0, 100): sleep(0.01) for k, v in stats.items(): print("task_switch[%5d->%5d]=%u" % (k.prev_pid, k.curr_pid, v.value))
def test_brb(self): try: b = BPF(src_file=arg1, debug=0) self.pem_fn = b.load_func("pem", BPF.SCHED_CLS) self.br1_fn = b.load_func("br1", BPF.SCHED_CLS) self.br2_fn = b.load_func("br2", BPF.SCHED_CLS) self.get_table(b) # 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.vm1_mac = ns1_ipdb.interfaces['eth0'].address self.vm2_mac = ns2_ipdb.interfaces['eth0'].address (_, self.nsrtr_eth0_out, _) = sim._create_ns(self.ns_router, ipaddr=self.vm1_rtr_ip + '/24', fn=self.br1_fn, action='drop', 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', fn=self.br2_fn, action='drop', disable_ipv6=True) nsp = NSPopen(rt_ipdb.nl.netns, ["sysctl", "-w", "net.ipv4.ip_forward=1"]) nsp.wait() nsp.release() # configure maps self.config_maps() # our bridge is not smart enough, so send arping for router learning to prevent router # from sending out arp request nsp = NSPopen(ns1_ipdb.nl.netns, [ "arping", "-w", "1", "-c", "1", "-I", "eth0", self.vm1_rtr_ip ]) nsp.wait() nsp.release() nsp = NSPopen(ns2_ipdb.nl.netns, [ "arping", "-w", "1", "-c", "1", "-I", "eth0", self.vm2_rtr_ip ]) nsp.wait() nsp.release() # ping nsp = NSPopen(ns1_ipdb.nl.netns, ["ping", self.vm2_ip, "-c", "2"]) nsp.wait() nsp.release() # pem_stats only counts pem->bridge traffic, each VM has 4: arping/arp request/2 icmp request # total 8 packets should be counted self.assertEqual(self.pem_stats[c_uint(0)].value, 8) 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: sim.release() ipdb.release()
# | clsfy_neigh() | | ^ \------/ | # lan1 ----|->->->->->->->-| <--1Mb--| | | # lan2 ----|->->->->->->->-| | classify_wan() | # ^ \------------/ | # pass() | from bpf import BPF from pyroute2 import IPRoute, NetNS, IPDB, NSPopen from simulation import Simulation import sys from time import sleep from builtins import input ipr = IPRoute() ipdb = IPDB(nl=ipr) b = BPF(src_file="tc_neighbor_sharing.c", debug=0) wan_fn = b.load_func("classify_wan", BPF.SCHED_CLS) pass_fn = b.load_func("pass", BPF.SCHED_CLS) neighbor_fn = b.load_func("classify_neighbor", BPF.SCHED_CLS) num_neighbors = 3 num_locals = 2 # class to build the simulation network class SharedNetSimulation(Simulation): def __init__(self, ipdb): super(SharedNetSimulation, self).__init__(ipdb) # Create the wan namespace, and attach an ingress filter for throttling
#!/usr/bin/python # # disksnoop.py Trace block device I/O: basic version of iosnoop. # For Linux, uses BCC, eBPF. See .c file. # # Written as a basic example of tracing latency. # # 11-Aug-2015 Brendan Gregg Created this. from bpf import BPF import sys REQ_WRITE = 1 # from include/linux/blk_types.h # load BPF program b = BPF(src_file="disksnoop.c") BPF.attach_kprobe(b.load_func("do_request", BPF.KPROBE), "blk_start_request") BPF.attach_kprobe(b.load_func("do_completion", BPF.KPROBE), "blk_update_request") # header print "%-18s %-2s %-7s %8s" % ("TIME(s)", "T", "BYTES", "LAT(ms)") # open trace pipe try: trace = open("/sys/kernel/debug/tracing/trace_pipe", "r") except: print >> sys.stderr, "ERROR: opening trace_pipe" exit(1) # format output while 1:
# arguments interval = 5 count = -1 if len(argv) > 1: try: interval = int(argv[1]) if interval == 0: raise if len(argv) > 2: count = int(argv[2]) except: # also catches -h, --help usage() # load BPF program b = BPF(src_file = "vfsreadlat.c") b.attach_kprobe(event="vfs_read", fn_name="do_entry") b.attach_kretprobe(event="vfs_read", fn_name="do_return") dist_max = 64 # header print("Tracing... Hit Ctrl-C to end.") # functions stars_max = 38 def stars(val, val_max, width): i = 0 text = "" while (1): if (i > (width * val / val_max) - 1) or (i > width - 1): break
# Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") from bpf import BPF from ctypes import c_uint, c_int, c_ulonglong, Structure import json from netaddr import IPAddress from os import rename from pyroute2 import IPRoute, NetNS, IPDB, NSPopen import sys from time import sleep ipr = IPRoute() ipdb = IPDB(nl=ipr) b = BPF(src_file="monitor.c", debug=0) ingress_fn = b.load_func("handle_ingress", BPF.SCHED_CLS) egress_fn = b.load_func("handle_egress", BPF.SCHED_CLS) outer_fn = b.load_func("handle_outer", BPF.SCHED_CLS) inner_fn = b.load_func("handle_inner", BPF.SCHED_CLS) stats = b.get_table("stats") # using jump table for inner and outer packet split parser = b.get_table("parser") parser[c_int(1)] = c_int(outer_fn.fd) parser[c_int(2)] = c_int(inner_fn.fd) ifc = ipdb.interfaces.eth0 ipr.tc("add", "ingress", ifc.index, "ffff:") ipr.tc("add-filter", "bpf", ifc.index, ":1", fd=ingress_fn.fd, name=ingress_fn.name, parent="ffff:", action="ok", classid=1)
def setUp(self): b = BPF(text=text, debug=0) fn = b.load_func("count_sched", BPF.KPROBE) self.stats = b.get_table("stats") BPF.attach_kprobe(fn, "schedule+50", 0, -1)
# Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") from bpf import BPF from ctypes import c_uint, c_int, c_ulonglong, Structure import json from netaddr import IPAddress from os import rename from pyroute2 import IPRoute, NetNS, IPDB, NSPopen import sys from time import sleep ipr = IPRoute() ipdb = IPDB(nl=ipr) b = BPF(src_file="monitor.c", debug=0) ingress_fn = b.load_func("handle_ingress", BPF.SCHED_CLS) egress_fn = b.load_func("handle_egress", BPF.SCHED_CLS) outer_fn = b.load_func("handle_outer", BPF.SCHED_CLS) inner_fn = b.load_func("handle_inner", BPF.SCHED_CLS) stats = b.get_table("stats") # using jump table for inner and outer packet split parser = b.get_table("parser") parser[c_int(1)] = c_int(outer_fn.fd) parser[c_int(2)] = c_int(inner_fn.fd) ifc = ipdb.interfaces.eth0 ipr.tc("add", "ingress", ifc.index, "ffff:") ipr.tc("add-filter", "bpf",
def test_complex(self): b = BPF(src_file="test_clang_complex.c", debug=0) fn = b.load_func("handle_packet", BPF.SCHED_CLS)
#!/usr/bin/python # Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") from bpf import BPF from time import sleep b = BPF(src_file="task_switch.c") b.attach_kprobe(event="finish_task_switch", fn_name="count_sched") # generate many schedule events for i in range(0, 100): sleep(0.01) for k, v in b["stats"].items(): print("task_switch[%5d->%5d]=%u" % (k.prev_pid, k.curr_pid, v.value))
# arguments interval = 1 count = -1 if len(argv) > 1: try: interval = int(argv[1]) if interval == 0: raise if len(argv) > 2: count = int(argv[2]) except: # also catches -h, --help usage() # load BPF program b = BPF(src_file="vfsstat.c") BPF.attach_kprobe(b.load_func("do_read", BPF.KPROBE), "vfs_read") BPF.attach_kprobe(b.load_func("do_write", BPF.KPROBE), "vfs_write") BPF.attach_kprobe(b.load_func("do_fsync", BPF.KPROBE), "vfs_fsync") BPF.attach_kprobe(b.load_func("do_open", BPF.KPROBE), "vfs_open") BPF.attach_kprobe(b.load_func("do_create", BPF.KPROBE), "vfs_create") stats = b.get_table("stats", c_int, c_ulonglong) # stat column labels and indexes stat_types = {"READ": 1, "WRITE": 2, "FSYNC": 3, "OPEN": 4, "CREATE": 5} # header print("%-8s " % "TIME", end="") last = {} for stype in stat_types.keys(): print(" %8s" % (stype + "/s"), end="")
end = len(ksym_addrs) while end != start + 1: mid = (start + end) / 2 if addr < ksym_addrs[mid]: end = mid else: start = mid if start == -1: return "[unknown]" return ksym_names[start] load_kallsyms() # load BPF program b = BPF(src_file="vfscount.c") fn = b.load_func("do_count", BPF.KPROBE) BPF.attach_kprobe(fn, "vfs_read") BPF.attach_kprobe(fn, "vfs_write") BPF.attach_kprobe(fn, "vfs_fsync") BPF.attach_kprobe(fn, "vfs_open") BPF.attach_kprobe(fn, "vfs_create") counts = b.get_table("counts") # header print "Tracing... Ctrl-C to end." # output try: sleep(99999999) except KeyboardInterrupt:
# Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") from bpf import BPF from pyroute2 import IPRoute ipr = IPRoute() text = """ int hello(struct __sk_buff *skb) { return 1; } """ try: b = BPF(text=text, debug=0) fn = b.load_func("hello", BPF.SCHED_CLS) ipr.link_create(ifname="t1a", kind="veth", peer="t1b") idx = ipr.link_lookup(ifname="t1a")[0] ipr.tc("add", "ingress", idx, "ffff:") ipr.tc("add-filter", "bpf", idx, ":1", fd=fn.fd, name=fn.name, parent="ffff:", action="ok", classid=1) ipr.tc("add", "sfq", idx, "1:")
#!/usr/bin/env python # Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") # run in project examples directory with: # sudo ./hello_world.py" from bpf import BPF prog = """ int hello(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; } """ b = BPF(text=prog) b.attach_kprobe(event="sys_clone", fn_name="hello") b.trace_print(fmt="{1} {5}")
# arguments interval = 5 count = -1 if len(argv) > 1: try: interval = int(argv[1]) if interval == 0: raise if len(argv) > 2: count = int(argv[2]) except: # also catches -h, --help usage() # load BPF program b = BPF(src_file = "vfsreadlat.c") BPF.attach_kprobe(b.load_func("do_entry", BPF.KPROBE), "vfs_read") BPF.attach_kretprobe(b.load_func("do_return", BPF.KPROBE), "vfs_read") dist = b.get_table("dist", c_int, c_ulonglong) dist_max = 64 # header print("Tracing... Hit Ctrl-C to end.") last = {} for i in range(1, dist_max + 1): last[i] = 0 # functions stars_max = 38 def stars(val, val_max, width): i = 0
def ksym(addr): start = -1 end = len(ksym_addrs) while end != start + 1: mid = (start + end) / 2 if addr < ksym_addrs[mid]: end = mid else: start = mid if start == -1: return "[unknown]" return ksym_names[start] load_kallsyms() # load BPF program b = BPF(src_file = "vfscount.c") fn = b.load_func("do_count", BPF.KPROBE) BPF.attach_kprobe(fn, "vfs_read") BPF.attach_kprobe(fn, "vfs_write") BPF.attach_kprobe(fn, "vfs_fsync") BPF.attach_kprobe(fn, "vfs_open") BPF.attach_kprobe(fn, "vfs_create") counts = b.get_table("counts") # header print "Tracing... Ctrl-C to end." # output try: sleep(99999999) except KeyboardInterrupt:
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()
def setUp(self): b = BPF(arg1, arg2, debug=0) fn1 = b.load_func("sys_wr", BPF.KPROBE) fn2 = b.load_func("sys_rd", BPF.KPROBE) fn3 = b.load_func("sys_bpf", BPF.KPROBE) self.stats = b.get_table("stats", Key, Leaf) BPF.attach_kprobe(fn1, "sys_write", 0, -1) BPF.attach_kprobe(fn2, "sys_read", 0, -1) BPF.attach_kprobe(fn2, "htab_map_get_next_key", 0, -1)
# arguments interval = 5 count = -1 if len(argv) > 1: try: interval = int(argv[1]) if interval == 0: raise if len(argv) > 2: count = int(argv[2]) except: # also catches -h, --help usage() # load BPF program b = BPF(src_file="bitehist.c") BPF.attach_kprobe(b.load_func("do_request", BPF.KPROBE), "blk_start_request") dist = b.get_table("dist", c_int, c_ulonglong) dist_max = 64 # header print("Tracing... Hit Ctrl-C to end.") last = {} for i in range(1, dist_max + 1): last[i] = 0 # functions stars_max = 38 def stars(val, val_max, width):
#!/usr/bin/python # # pidpersec.py Count new processes (via fork). # For Linux, uses BCC, eBPF. See .c file. # # Written as a basic example of counting an event. # # 11-Aug-2015 Brendan Gregg Created this. from bpf import BPF from ctypes import c_ushort, c_int, c_ulonglong from time import sleep, strftime # load BPF program b = BPF(src_file="pidpersec.c") BPF.attach_kprobe(b.load_func("do_count", BPF.KPROBE), "sched_fork") stats = b.get_table("stats", c_int, c_ulonglong) # stat indexes S_COUNT = 1 # header print "Tracing... Ctrl-C to end." # output last = 0 while (1): try: sleep(1) except KeyboardInterrupt: pass