• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# xdp_redirect_cpu.py Redirect the incoming packet to the specific CPU
4#
5# Copyright (c) 2018 Gary Lin
6# Licensed under the Apache License, Version 2.0 (the "License")
7
8from bcc import BPF
9import time
10import sys
11from multiprocessing import cpu_count
12import ctypes as ct
13
14flags = 0
15def usage():
16    print("Usage: {0} <in ifdev> <CPU id>".format(sys.argv[0]))
17    print("e.g.: {0} eth0 2\n".format(sys.argv[0]))
18    exit(1)
19
20if len(sys.argv) != 3:
21    usage()
22
23in_if = sys.argv[1]
24cpu_id = int(sys.argv[2])
25
26max_cpu = cpu_count()
27if (cpu_id > max_cpu):
28    print("Invalid CPU id")
29    exit(1)
30
31# load BPF program
32b = BPF(text = """
33#define KBUILD_MODNAME "foo"
34#include <uapi/linux/bpf.h>
35#include <linux/in.h>
36#include <linux/if_ether.h>
37
38BPF_CPUMAP(cpumap, __MAX_CPU__);
39BPF_ARRAY(dest, uint32_t, 1);
40BPF_PERCPU_ARRAY(rxcnt, long, 1);
41
42int xdp_redirect_cpu(struct xdp_md *ctx) {
43    void* data_end = (void*)(long)ctx->data_end;
44    void* data = (void*)(long)ctx->data;
45    struct ethhdr *eth = data;
46    uint32_t key = 0;
47    long *value;
48    uint32_t *cpu;
49    uint64_t nh_off;
50
51    nh_off = sizeof(*eth);
52    if (data + nh_off  > data_end)
53        return XDP_DROP;
54
55    cpu = dest.lookup(&key);
56    if (!cpu)
57        return XDP_PASS;
58
59    value = rxcnt.lookup(&key);
60    if (value)
61        *value += 1;
62
63    return cpumap.redirect_map(*cpu, 0);
64}
65
66int xdp_dummy(struct xdp_md *ctx) {
67    return XDP_PASS;
68}
69""", cflags=["-w", "-D__MAX_CPU__=%u" % max_cpu], debug=0)
70
71dest = b.get_table("dest")
72dest[0] = ct.c_uint32(cpu_id)
73
74cpumap = b.get_table("cpumap")
75cpumap[cpu_id] = ct.c_uint32(192)
76
77in_fn = b.load_func("xdp_redirect_cpu", BPF.XDP)
78b.attach_xdp(in_if, in_fn, flags)
79
80rxcnt = b.get_table("rxcnt")
81prev = 0
82print("Printing redirected packets, hit CTRL+C to stop")
83while 1:
84    try:
85        val = rxcnt.sum(0).value
86        if val:
87            delta = val - prev
88            prev = val
89            print("{} pkt/s to CPU {}".format(delta, cpu_id))
90        time.sleep(1)
91    except KeyboardInterrupt:
92        print("Removing filter from device")
93        break
94
95b.remove_xdp(in_if, flags)
96