• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/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#include <uapi/linux/bpf.h>
34#include <linux/in.h>
35#include <linux/if_ether.h>
36
37BPF_CPUMAP(cpumap, __MAX_CPU__);
38BPF_ARRAY(dest, uint32_t, 1);
39BPF_PERCPU_ARRAY(rxcnt, long, 1);
40
41int xdp_redirect_cpu(struct xdp_md *ctx) {
42    void* data_end = (void*)(long)ctx->data_end;
43    void* data = (void*)(long)ctx->data;
44    struct ethhdr *eth = data;
45    uint32_t key = 0;
46    long *value;
47    uint32_t *cpu;
48    uint64_t nh_off;
49
50    nh_off = sizeof(*eth);
51    if (data + nh_off  > data_end)
52        return XDP_DROP;
53
54    cpu = dest.lookup(&key);
55    if (!cpu)
56        return XDP_PASS;
57
58    value = rxcnt.lookup(&key);
59    if (value)
60        *value += 1;
61
62    return cpumap.redirect_map(*cpu, 0);
63}
64""", cflags=["-w", "-D__MAX_CPU__=%u" % max_cpu], debug=0)
65
66dest = b.get_table("dest")
67dest[0] = ct.c_uint32(cpu_id)
68
69cpumap = b.get_table("cpumap")
70cpumap[cpu_id] = ct.c_uint32(192)
71
72in_fn = b.load_func("xdp_redirect_cpu", BPF.XDP)
73b.attach_xdp(in_if, in_fn, flags)
74
75rxcnt = b.get_table("rxcnt")
76prev = 0
77print("Printing redirected packets, hit CTRL+C to stop")
78while 1:
79    try:
80        val = rxcnt.sum(0).value
81        if val:
82            delta = val - prev
83            prev = val
84            print("{} pkt/s to CPU {}".format(delta, cpu_id))
85        time.sleep(1)
86    except KeyboardInterrupt:
87        print("Removing filter from device")
88        break
89
90b.remove_xdp(in_if, flags)
91