From 917a9e56b7a0ade6083b9786e2921c4e11197543 Mon Sep 17 00:00:00 2001 From: Martin Teichmann <martin.teichmann@xfel.eu> Date: Tue, 22 Dec 2020 11:55:27 +0000 Subject: [PATCH] got XDP running! still very ugly --- bpf.py | 2 -- ebpfcat.py | 20 ++++++++++++++++++-- ethercat.py | 5 +++++ xdp.py | 35 +++++++++++++++++++++++++++-------- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/bpf.py b/bpf.py index 3123e35..f7057e4 100644 --- a/bpf.py +++ b/bpf.py @@ -38,9 +38,7 @@ def addrof(ptr): def bpf(cmd, fmt, *args): attr = pack(fmt, *args) attr = create_string_buffer(attr, len(attr)) - print(unpack(fmt, attr.raw)) ret = libc.syscall(386, c_int(cmd), attr, len(attr)) - print(unpack(fmt, attr.raw)) if ret == -1: raise OSError(get_errno(), strerror(get_errno())) return ret, unpack(fmt, attr.raw) diff --git a/ebpfcat.py b/ebpfcat.py index 80528d4..516ddf4 100644 --- a/ebpfcat.py +++ b/ebpfcat.py @@ -1,3 +1,6 @@ +from asyncio import ensure_future, sleep +from struct import unpack +from time import time from .xdp import set_link_xdp_fd from .ebpf import EBPF from .bpf import ProgType, create_map, update_elem, prog_test_run, lookup_elem @@ -17,7 +20,7 @@ def script(): e.r2 = e.r10 e.r2 += -8 e.r3 = e.m32[e.r0] - e.r3 += 1 + e.r3 -= 1 e.m32[e.r10 - 16] = e.r3 e.r3 = e.r10 e.r3 += -16 @@ -27,11 +30,24 @@ def script(): e.exit() return fd, e +async def logger(map_fd): + lasttime = time() + lastno = 0x42424242 + while True: + r = lookup_elem(map_fd, b"AAAA", 4) + no, = unpack("i", r) + t = time() + print(f"L {no:7} {lastno-no:7} {t-lasttime:7.3f} {(lastno-no)/(t-lasttime):7.1f}") + lasttime = t + lastno = no + await sleep(0.1) + async def install_ebpf(network): map_fd, e = script() fd, disas = e.load(log_level=1) + print(disas) prog_test_run(fd, 512, 512, 512, 512, repeat=10) - print("bla", lookup_elem(map_fd, b"AAAAA", 4)) + ensure_future(logger(map_fd)) await set_link_xdp_fd("eth0", fd) return map_fd diff --git a/ethercat.py b/ethercat.py index 11b2d2a..2f7154e 100644 --- a/ethercat.py +++ b/ethercat.py @@ -402,7 +402,11 @@ class Terminal: async def main(): + from .ebpfcat import install_ebpf + from .bpf import lookup_elem + ec = await EtherCat("eth0") + map_fd = await install_ebpf("eth0") tin = Terminal(ec) tout = Terminal(ec) tdigi = Terminal(ec) @@ -426,6 +430,7 @@ async def main(): except RuntimeError as e: print(" ", e) print("tdigi") + print("bla", lookup_elem(map_fd, b"AAAA", 4)) await tdigi.to_operational(), print(tout.eeprom[10]) diff --git a/xdp.py b/xdp.py index e90e7ac..4ad8384 100644 --- a/xdp.py +++ b/xdp.py @@ -1,5 +1,6 @@ from asyncio import DatagramProtocol, Future, get_event_loop from socket import AF_NETLINK, NETLINK_ROUTE, if_nametoindex +import socket from struct import pack, unpack async def set_link_xdp_fd(network, fd): @@ -8,6 +9,8 @@ async def set_link_xdp_fd(network, fd): transport, proto = await get_event_loop().create_datagram_endpoint( lambda: XDRFD(ifindex, fd, future), family=AF_NETLINK, proto=NETLINK_ROUTE) + await future + transport.get_extra_info("socket").close() class XDRFD(DatagramProtocol): def __init__(self, ifindex, fd, future): @@ -17,35 +20,51 @@ class XDRFD(DatagramProtocol): self.future = future def connection_made(self, transport): - transport.get_extra_info("socket").bind((0, 0)) + sock = transport.get_extra_info("socket") + sock.setsockopt(270, 11, 1) + sock.bind((0, 0)) self.transport = transport - p = pack("IHHIIBxHiIIHHHHi", - 16, # length of if struct + p = pack("IHHIIBxHiIiHHHHiHHI", + # NLmsghdr + 52, # length of if struct 19, # RTM_SETLINK 5, # REQ | ACK 1, # sequence number 0, # pid + # IFI 0, # AF_UNSPEC 0, # type self.ifindex, 0, #flags 0, #change + # NLA + 20, # length of field 0x802B, # NLA_F_NESTED | IFLA_XDP - 12, # length of field - 1, # IFLA_XDP_FD + # NLA_XDP 8, # length of field - self.fd) + 1, # IFLA_XDP_FD + self.fd, + 8, + 3, # IFLA_XDP_FLAGS, + 2) + print("send", len(p), p) transport.sendto(p, (0, 0)) def datagram_received(self, data, addr): pos = 0 + print("received", data) while (pos < len(data)): ln, type, flags, seq, pid = unpack("IHHII", data[pos : pos+16]) + print(f" {ln} {type} {flags:x} {seq} {pid}") if type == 3: # DONE self.future.set_result(0) elif type == 2: # ERROR - self.future.set_result(-1) - elif flags & 2 == 0: # not a multipart message + errno, *args = unpack("iIHHII", data[pos+16 : pos+36]) + print("ERROR", errno, args) + if errno != 0: + self.future.set_result(errno) + if flags & 2 == 0: # not a multipart message + print("not multipart") self.future.set_result(0) pos += ln -- GitLab