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