Open 4ast opened 8 years ago
Hi,
I added xdp support to bcc, if there is an interest I can file a pull request! (https://github.com/Eichhoernchen/bcc/commit/43462f45457e3221d61307c6c44e1aaeffa09235)
Todo so I added a method attach_xdp that takes a function and an interface name as an argument. Here is an example (I used the xdp1_kern.c example from the xdp devel branch):
from bcc import BPF
import time
# load BPF program
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("percpu_array", 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 xdp_md *ctx) {
void* data_end = (void*)(long)ctx->data_end;
void* data = (void*)(long)ctx->data;
struct ethhdr *eth = data;
// drop packets
int rc = XDP_DROP; // 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;
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_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)
*value += 1;
return rc;
}
""")
xdp_func = b.load_func("xdp_prog1", BPF.XDP)
b.attach_xdp(xdp_func, "enp0s3")
dropcnt = b.get_table("dropcnt")
while 1:
for k in dropcnt.keys():
if (dropcnt.sum(k).value > 0):
print("{}: {}".format(k.value, dropcnt.sum(k).value))
time.sleep(1)
I'm still undecided if I prefer having the interface before the function...
I basically refactored and adapted parts of xdp1_user.c for libbpf.
nice! the first xdp patch set is close enough to net-next. Looking forward to your PR as soon as it lands, since there still can be minor changes in uapi. Like the most recent addition of XDP_ABORT. Thanks!
cool, I will be monitoring the changes and merge them and once xdp is in net-next I'll file a PR
cc @brendangregg please add to the wish list :)
bpf testing
bpf core
bpf tracing
bpf llvm
bpf security
bpf testing
xdp