Commit 9f3cab70 authored by Andy Gospodarek's avatar Andy Gospodarek

Add support for generic XDP mode

Reused some of the code and command-line format from kernel XDP samples.

$ sudo ./xdp_drop_count.py -S enp1s0
Printing drops per IP protocol-number, hit CTRL+C to stop
17: 36616 pkt/s
17: 19720757 pkt/s
17: 19685768 pkt/s
17: 19643601 pkt/s
17: 19694537 pkt/s
[...]
$ sudo ./xdp_drop_count.py enp1s0
Printing drops per IP protocol-number, hit CTRL+C to stop
17: 7029 pkt/s
17: 29996706 pkt/s
17: 30048705 pkt/s
17: 30261417 pkt/s
17: 30291967 pkt/s
[...]

Throughput difference is expected since generic XDP takes more
instructions per packet than optimized XDP.

v2: switch __u32 to uint32_t in bpf_attach_xdp
Signed-off-by: default avatarAndy Gospodarek <gospo@broadcom.com>
parent 4b3d2b08
...@@ -12,11 +12,28 @@ import pyroute2 ...@@ -12,11 +12,28 @@ import pyroute2
import time import time
import sys import sys
if len(sys.argv) != 2: flags = 0
print("Usage: {0} <ifdev>\n\ne.g.: {0} eth0".format(sys.argv[0])) def usage():
print("Usage: {0} [-S] <ifdev>".format(sys.argv[0]))
print(" -S: use skb mode\n")
print("e.g.: {0} eth0\n".format(sys.argv[0]))
exit(1) exit(1)
device = sys.argv[1] if len(sys.argv) < 2 or len(sys.argv) > 3:
usage()
if len(sys.argv) == 2:
device = sys.argv[1]
if len(sys.argv) == 3:
if "-S" in sys.argv:
# XDP_FLAGS_SKB_MODE
flags |= 2 << 0
if "-S" == sys.argv[1]:
device = sys.argv[2]
else:
device = sys.argv[1]
mode = BPF.XDP mode = BPF.XDP
#mode = BPF.SCHED_CLS #mode = BPF.SCHED_CLS
...@@ -116,7 +133,7 @@ int xdp_prog1(struct CTXTYPE *ctx) { ...@@ -116,7 +133,7 @@ int xdp_prog1(struct CTXTYPE *ctx) {
fn = b.load_func("xdp_prog1", mode) fn = b.load_func("xdp_prog1", mode)
if mode == BPF.XDP: if mode == BPF.XDP:
b.attach_xdp(device, fn) b.attach_xdp(device, fn, flags)
else: else:
ip = pyroute2.IPRoute() ip = pyroute2.IPRoute()
ipdb = pyroute2.IPDB(nl=ip) ipdb = pyroute2.IPDB(nl=ip)
......
...@@ -649,7 +649,7 @@ int bpf_open_perf_event(uint32_t type, uint64_t config, int pid, int cpu) { ...@@ -649,7 +649,7 @@ int bpf_open_perf_event(uint32_t type, uint64_t config, int pid, int cpu) {
return fd; return fd;
} }
int bpf_attach_xdp(const char *dev_name, int progfd) { int bpf_attach_xdp(const char *dev_name, int progfd, uint32_t flags) {
struct sockaddr_nl sa; struct sockaddr_nl sa;
int sock, seq = 0, len, ret = -1; int sock, seq = 0, len, ret = -1;
char buf[4096]; char buf[4096];
...@@ -694,12 +694,22 @@ int bpf_attach_xdp(const char *dev_name, int progfd) { ...@@ -694,12 +694,22 @@ int bpf_attach_xdp(const char *dev_name, int progfd) {
nla->nla_type = NLA_F_NESTED | 43/*IFLA_XDP*/; nla->nla_type = NLA_F_NESTED | 43/*IFLA_XDP*/;
nla_xdp = (struct nlattr *)((char *)nla + NLA_HDRLEN); nla_xdp = (struct nlattr *)((char *)nla + NLA_HDRLEN);
nla->nla_len = NLA_HDRLEN;
// we specify the FD passed over by the user // we specify the FD passed over by the user
nla_xdp->nla_type = 1/*IFLA_XDP_FD*/; nla_xdp->nla_type = 1/*IFLA_XDP_FD*/;
nla_xdp->nla_len = NLA_HDRLEN + sizeof(progfd); nla_xdp->nla_len = NLA_HDRLEN + sizeof(progfd);
memcpy((char *)nla_xdp + NLA_HDRLEN, &progfd, sizeof(progfd)); memcpy((char *)nla_xdp + NLA_HDRLEN, &progfd, sizeof(progfd));
nla->nla_len = NLA_HDRLEN + nla_xdp->nla_len; nla->nla_len += nla_xdp->nla_len;
// parse flags as passed by the user
if (flags) {
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
nla_xdp->nla_type = 3/*IFLA_XDP_SKB*/;
nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
nla->nla_len += nla_xdp->nla_len;
}
req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len); req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
......
...@@ -75,7 +75,7 @@ void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, ...@@ -75,7 +75,7 @@ void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb,
int pid, int cpu, int page_cnt); int pid, int cpu, int page_cnt);
/* attached a prog expressed by progfd to the device specified in dev_name */ /* attached a prog expressed by progfd to the device specified in dev_name */
int bpf_attach_xdp(const char *dev_name, int progfd); int bpf_attach_xdp(const char *dev_name, int progfd, uint32_t flags);
// attach a prog expressed by progfd to run on a specific perf event, with // attach a prog expressed by progfd to run on a specific perf event, with
// certain sample period or sample frequency // certain sample period or sample frequency
......
...@@ -571,14 +571,14 @@ class BPF(object): ...@@ -571,14 +571,14 @@ class BPF(object):
self._del_kprobe(ev_name) self._del_kprobe(ev_name)
@staticmethod @staticmethod
def attach_xdp(dev, fn): def attach_xdp(dev, fn, flags):
''' '''
This function attaches a BPF function to a device on the device This function attaches a BPF function to a device on the device
driver level (XDP) driver level (XDP)
''' '''
if not isinstance(fn, BPF.Function): if not isinstance(fn, BPF.Function):
raise Exception("arg 1 must be of type BPF.Function") raise Exception("arg 1 must be of type BPF.Function")
res = lib.bpf_attach_xdp(dev.encode("ascii"), fn.fd) res = lib.bpf_attach_xdp(dev.encode("ascii"), fn.fd, flags)
if res < 0: if res < 0:
err_no = ct.get_errno() err_no = ct.get_errno()
if err_no == errno.EBADMSG: if err_no == errno.EBADMSG:
...@@ -595,7 +595,7 @@ class BPF(object): ...@@ -595,7 +595,7 @@ class BPF(object):
This function removes any BPF function from a device on the This function removes any BPF function from a device on the
device driver level (XDP) device driver level (XDP)
''' '''
res = lib.bpf_attach_xdp(dev.encode("ascii"), -1) res = lib.bpf_attach_xdp(dev.encode("ascii"), -1, 0)
if res < 0: if res < 0:
errstr = os.strerror(ct.get_errno()) errstr = os.strerror(ct.get_errno())
raise Exception("Failed to detach BPF from device %s: %s" raise Exception("Failed to detach BPF from device %s: %s"
......
...@@ -116,7 +116,7 @@ lib.perf_reader_fd.restype = int ...@@ -116,7 +116,7 @@ lib.perf_reader_fd.restype = int
lib.perf_reader_fd.argtypes = [ct.c_void_p] lib.perf_reader_fd.argtypes = [ct.c_void_p]
lib.bpf_attach_xdp.restype = ct.c_int; lib.bpf_attach_xdp.restype = ct.c_int;
lib.bpf_attach_xdp.argtypes = [ct.c_char_p, ct.c_int] lib.bpf_attach_xdp.argtypes = [ct.c_char_p, ct.c_int, ct.c_uint]
lib.bpf_attach_perf_event.restype = ct.c_int; lib.bpf_attach_perf_event.restype = ct.c_int;
lib.bpf_attach_perf_event.argtype = [ct.c_int, ct.c_uint, ct.c_uint, ct.c_ulonglong, ct.c_ulonglong, lib.bpf_attach_perf_event.argtype = [ct.c_int, ct.c_uint, ct.c_uint, ct.c_ulonglong, ct.c_ulonglong,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment