Received: by 10.223.176.5 with SMTP id f5csp450320wra; Tue, 30 Jan 2018 14:14:08 -0800 (PST) X-Google-Smtp-Source: AH8x224JEdHEC1dFp8Cq1SYhmNU8w1UzosKhiA09baYwk5zlrBAqcYN0VHDuIgaHnEKgeHLYWykJ X-Received: by 10.99.126.86 with SMTP id o22mr25277791pgn.364.1517350448527; Tue, 30 Jan 2018 14:14:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517350448; cv=none; d=google.com; s=arc-20160816; b=jqO1g0fY8lKIX7kN/l9NDcDooREJ4X6+u5q5+28ee9cVNorcZIafEdfClvpbqSoUVq wV3ATcM4jeJ0en8KmncDjDF5QqvGHWUPLBS+GGNjCSdzvxg9BS1PH5/Rstsbm6zBjwF9 EHf+lVgaUiChtNJ4/pG+GpE4Kgpv/6uQ8IAoFlEVQkA0/N9oVSsXuGjvdEDb4wI42O5N /8HoG6Ckf56KYPaaf2/6JC5whgMwhPZPc1VEj+xCSaIkHNfsnj1mJfmn/R9nyX2P3uI8 6QOiqQdhE7uYxKqQvm3oSgoyLgCi/zmZ6A6UhI/TGbbVZzw9M8jBo4a+blChTgm/mIEd R5JA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=JaMGfGK59EgYeFSbe1UQ6bw5r4kpz5Dk8XDT2d2G228=; b=Pom3OX2zBh1c8OwJQx0lzc9A/wcxLY9R7tIYn1S5TVehrKrU/OjIApnLxOOc8WX5BF CPF5KwFzBeotDYHXe7APK91ih1vnkoC85L7xU2mzJ5gvQP6yfthFCPs1Wqtll6Xd0UdA edOKqLZ7nqYDATcnbMPrn5rbEoOxpECXi58KqbLfK8U3fGQRF9yExldRzterI5J+ZNIk sfV1tXttiyez5powWMMQsx9ReboZXJzXbmVe+E51SCWqcbVmz8W7U/1ih4E+IjRB25xE cX2V46nhqR3R3PedP+RmVfIARPalHeAb8vdXe5riARLFmYKULQ6LCEly2wfYRkYQOAQ1 3cqQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f90-v6si203386plf.0.2018.01.30.14.13.53; Tue, 30 Jan 2018 14:14:07 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753551AbeA3U4v (ORCPT + 99 others); Tue, 30 Jan 2018 15:56:51 -0500 Received: from home.regit.org ([37.187.126.138]:37342 "EHLO home.regit.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753315AbeA3Uz2 (ORCPT ); Tue, 30 Jan 2018 15:55:28 -0500 Received: from [105.155.250.197] (helo=tiger2.controleur.qconnect.fr) by home.regit.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1egcw9-0007a3-GT; Tue, 30 Jan 2018 21:55:26 +0100 From: Eric Leblond To: daniel@iogearbox.net Cc: alexei.starovoitov@gmail.com, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Leblond Subject: [PATCH bpf-next v8 2/5] libbpf: add function to setup XDP Date: Tue, 30 Jan 2018 21:55:01 +0100 Message-Id: <20180130205504.20826-2-eric@regit.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180130205504.20826-1-eric@regit.org> References: <20180130205504.20826-1-eric@regit.org> X-Spam-Score: -1.0 (-) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Most of the code is taken from set_link_xdp_fd() in bpf_load.c and slightly modified to be library compliant. Signed-off-by: Eric Leblond Acked-by: Alexei Starovoitov --- tools/lib/bpf/bpf.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.c | 2 + tools/lib/bpf/libbpf.h | 4 ++ 3 files changed, 128 insertions(+) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 5128677e4117..bf2772566240 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -25,6 +25,12 @@ #include #include #include "bpf.h" +#include "libbpf.h" +#include "nlattr.h" +#include +#include +#include +#include /* * When building perf, unistd.h is overridden. __NR_bpf is @@ -46,7 +52,9 @@ # endif #endif +#ifndef min #define min(x, y) ((x) < (y) ? (x) : (y)) +#endif static inline __u64 ptr_to_u64(const void *ptr) { @@ -413,3 +421,117 @@ int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len) return err; } + +int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) +{ + struct sockaddr_nl sa; + int sock, seq = 0, len, ret = -1; + char buf[4096]; + struct nlattr *nla, *nla_xdp; + struct { + struct nlmsghdr nh; + struct ifinfomsg ifinfo; + char attrbuf[64]; + } req; + struct nlmsghdr *nh; + struct nlmsgerr *err; + socklen_t addrlen; + + memset(&sa, 0, sizeof(sa)); + sa.nl_family = AF_NETLINK; + + sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (sock < 0) { + return -errno; + } + + if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { + ret = -errno; + goto cleanup; + } + + addrlen = sizeof(sa); + if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) { + ret = -errno; + goto cleanup; + } + + if (addrlen != sizeof(sa)) { + ret = -LIBBPF_ERRNO__INTERNAL; + goto cleanup; + } + + memset(&req, 0, sizeof(req)); + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + req.nh.nlmsg_type = RTM_SETLINK; + req.nh.nlmsg_pid = 0; + req.nh.nlmsg_seq = ++seq; + req.ifinfo.ifi_family = AF_UNSPEC; + req.ifinfo.ifi_index = ifindex; + + /* started nested attribute for XDP */ + nla = (struct nlattr *)(((char *)&req) + + NLMSG_ALIGN(req.nh.nlmsg_len)); + nla->nla_type = NLA_F_NESTED | IFLA_XDP; + nla->nla_len = NLA_HDRLEN; + + /* add XDP fd */ + nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); + nla_xdp->nla_type = IFLA_XDP_FD; + nla_xdp->nla_len = NLA_HDRLEN + sizeof(int); + memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd)); + nla->nla_len += nla_xdp->nla_len; + + /* if user passed in any flags, add those too */ + if (flags) { + nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); + nla_xdp->nla_type = IFLA_XDP_FLAGS; + 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); + + if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) { + ret = -errno; + goto cleanup; + } + + len = recv(sock, buf, sizeof(buf), 0); + if (len < 0) { + ret = -errno; + goto cleanup; + } + + for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); + nh = NLMSG_NEXT(nh, len)) { + if (nh->nlmsg_pid != sa.nl_pid) { + ret = -LIBBPF_ERRNO__WRNGPID; + goto cleanup; + } + if (nh->nlmsg_seq != seq) { + ret = -LIBBPF_ERRNO__INVSEQ; + goto cleanup; + } + switch (nh->nlmsg_type) { + case NLMSG_ERROR: + err = (struct nlmsgerr *)NLMSG_DATA(nh); + if (!err->error) + continue; + ret = err->error; + goto cleanup; + case NLMSG_DONE: + break; + default: + break; + } + } + + ret = 0; + +cleanup: + close(sock); + return ret; +} diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 30c776375118..c60122d3ea85 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -106,6 +106,8 @@ static const char *libbpf_strerror_table[NR_ERRNO] = { [ERRCODE_OFFSET(PROG2BIG)] = "Program too big", [ERRCODE_OFFSET(KVER)] = "Incorrect kernel version", [ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type", + [ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message", + [ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence", }; int libbpf_strerror(int err, char *buf, size_t size) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 6e20003109e0..e42f96900318 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -42,6 +42,8 @@ enum libbpf_errno { LIBBPF_ERRNO__PROG2BIG, /* Program too big */ LIBBPF_ERRNO__KVER, /* Incorrect kernel version */ LIBBPF_ERRNO__PROGTYPE, /* Kernel doesn't support this program type */ + LIBBPF_ERRNO__WRNGPID, /* Wrong pid in netlink message */ + LIBBPF_ERRNO__INVSEQ, /* Invalid netlink sequence */ __LIBBPF_ERRNO__END, }; @@ -246,4 +248,6 @@ long libbpf_get_error(const void *ptr); int bpf_prog_load(const char *file, enum bpf_prog_type type, struct bpf_object **pobj, int *prog_fd); + +int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags); #endif -- 2.15.1