OffloadUtils - add support for attaching/detaching XDP programs

Test: atest, TreeHugger
Signed-off-by: Maciej ┼╗enczykowski <maze@google.com>
Change-Id: I717029f1063aa8aeb7fd036cc38bd852ad41c76e
diff --git a/server/OffloadUtils.cpp b/server/OffloadUtils.cpp
index 47bc6a4..f334a29 100644
--- a/server/OffloadUtils.cpp
+++ b/server/OffloadUtils.cpp
@@ -147,6 +147,64 @@
     return resp.e.error;  // returns 0 on success
 }
 
+int doSetXDP(int ifIndex, int fd, __u32 flags) {
+    const struct {
+        nlmsghdr n;
+        ifinfomsg i;
+        struct {
+            nlattr attr;
+            struct {
+                nlattr attr;
+                int value;
+            } fd;
+            struct {
+                nlattr attr;
+                __u32 value;
+            } flags;
+        } nested;
+    } req = {
+            .n =
+                    {
+                            .nlmsg_len = sizeof(req),
+                            .nlmsg_type = RTM_SETLINK,
+                            .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+                    },
+            .i =
+                    {
+                            .ifi_family = AF_UNSPEC,
+                            .ifi_index = ifIndex,
+                    },
+            .nested =
+                    {
+                            .attr =
+                                    {
+                                            .nla_len = sizeof(req.nested),
+                                            .nla_type = NLA_F_NESTED | IFLA_XDP,
+                                    },
+                            .fd =
+                                    {
+                                            .attr =
+                                                    {
+                                                            .nla_len = sizeof(req.nested.fd),
+                                                            .nla_type = IFLA_XDP_FD,
+                                                    },
+                                            .value = fd,  // -1 means remove
+                                    },
+                            .flags =
+                                    {
+                                            .attr =
+                                                    {
+                                                            .nla_len = sizeof(req.nested.flags),
+                                                            .nla_type = IFLA_XDP_FLAGS,
+                                                    },
+                                            .value = flags,
+                                    },
+                    },
+    };
+
+    return sendAndProcessNetlinkResponse(&req, sizeof(req));
+}
+
 // ADD:     nlMsgType=RTM_NEWQDISC nlMsgFlags=NLM_F_EXCL|NLM_F_CREATE
 // REPLACE: nlMsgType=RTM_NEWQDISC nlMsgFlags=NLM_F_CREATE|NLM_F_REPLACE
 // DEL:     nlMsgType=RTM_DELQDISC nlMsgFlags=0
diff --git a/server/OffloadUtils.h b/server/OffloadUtils.h
index 9b6b1e8..fa3e6f4 100644
--- a/server/OffloadUtils.h
+++ b/server/OffloadUtils.h
@@ -19,6 +19,7 @@
 #include <android-base/result.h>
 #include <errno.h>
 #include <linux/if_ether.h>
+#include <linux/if_link.h>
 #include <linux/rtnetlink.h>
 
 #include <string>
@@ -173,6 +174,23 @@
                       : getTetherUpstreamXdpProgFd(with_ethernet_header);
 }
 
+int doSetXDP(int ifIndex, int fd, __u32 flags);
+
+inline int addXDP(int ifIndex, int fd, int mode = XDP_FLAGS_DRV_MODE) {
+    if (fd < 0) return -EBADF;
+    return doSetXDP(ifIndex, fd, mode | XDP_FLAGS_UPDATE_IF_NOEXIST);
+}
+
+inline int setXDP(int ifIndex, int fd, int mode = XDP_FLAGS_DRV_MODE) {
+    if (fd < 0) return -EBADF;
+    return doSetXDP(ifIndex, fd, mode);
+}
+
+inline int removeXDP(int ifIndex, int mode = XDP_FLAGS_DRV_MODE) {
+    // an fd of -1 means to remove
+    return doSetXDP(ifIndex, -1, mode);
+}
+
 int doTcQdiscClsact(int ifIndex, uint16_t nlMsgType, uint16_t nlMsgFlags);
 
 inline int tcQdiscAddDevClsact(int ifIndex) {