Received: by 10.223.176.46 with SMTP id f43csp175925wra; Thu, 18 Jan 2018 15:45:39 -0800 (PST) X-Google-Smtp-Source: ACJfBovXcqhBQpJpG0CouRJCvWzb1ldNgCcBe4HmzccqulgLkeiVnmlaVcWKtSmozx1/GLSRP8TC X-Received: by 10.99.116.22 with SMTP id p22mr34286552pgc.4.1516319139721; Thu, 18 Jan 2018 15:45:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516319139; cv=none; d=google.com; s=arc-20160816; b=p6O+5jLX45uok72WMG7I5XQt/GgW5KcQEKpKXkl10yZbt1bvs6jAT1AmPjoersXvbV NljaKBn+1GqwqDoR8JmQdlLFswal9HrT4Kgs3LILJPh88XZu9HbRyqKIcwCECh6PHtRj KsCbIYCRBrP+MFD+tntankBWjE5ycEIqtEwukwYSqtyS6BzAno3VScVPPnOfRIZZguq+ K2sbDYlRmpa5XXJfZ0Yt09yNg27pWMQXsIqPuCZWHsgVgr5YZiNSz13aUbOSXkarfAXx RPEBy33OXovB8dOcGazs1kSGOEjTOvCDLfnyFIas9sc03TuvHblnKDwM6XwX9uZw3Ki+ aYhw== 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=BH/bhwRLz21a5u24ohciBZcyELMeN+qS++JePFbKDv8=; b=npX+ubKWppjuqJJkvMtXGOqMa73MuQh0i/jOFO1SCWv8xcrzIFgNCQrYtNHyEvgW0M ZF0fHYmQqpjhq4PHtjfiCgsJ9eF5N0e6Us4smZSNjElQc0yw9P8okt4v/zPRNjq3dJm2 UOZmTzcsEEpRp0zV7qVcBr3Y07fShrP6KRM+mX7OEYXpcepGAl/nbMgqvP7nkApkFu5L J83bezcByxAIGs+qrbt6Knhc8fHDyPJQwKkDulCzJzIfMjoHIpTdfId8s3bj+OI9a44V 7T8NnkyBeoJK7rGLxNJA2XeFohd5a4jFz+sGNLpzZxTTZiTbWGFmmB8EuoExOlLUMbRK xMmg== 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 c20si7988564pfl.166.2018.01.18.15.45.26; Thu, 18 Jan 2018 15:45:39 -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 S932942AbeARXoq (ORCPT + 99 others); Thu, 18 Jan 2018 18:44:46 -0500 Received: from home.regit.org ([37.187.126.138]:43640 "EHLO home.regit.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932620AbeARXnx (ORCPT ); Thu, 18 Jan 2018 18:43:53 -0500 Received: from va-67-76-165-20.dyn.embarqhsd.net ([67.76.165.20] helo=tiger2.fidelis.farm) by home.regit.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1ecJqY-0004yx-8N; Fri, 19 Jan 2018 00:43:51 +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 v6 1/4] libbpf: add function to setup XDP Date: Fri, 19 Jan 2018 00:43:29 +0100 Message-Id: <20180118234332.28996-2-eric@regit.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180118234332.28996-1-eric@regit.org> References: <1516318537.24936.7.camel@regit.org> <20180118234332.28996-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 | 126 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.c | 2 + tools/lib/bpf/libbpf.h | 4 ++ 3 files changed, 132 insertions(+) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 5128677e4117..e6c61035b64c 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -25,6 +25,16 @@ #include #include #include "bpf.h" +#include "libbpf.h" +#include +#include +#include + +#ifndef IFLA_XDP_MAX +#define IFLA_XDP 43 +#define IFLA_XDP_FD 1 +#define IFLA_XDP_FLAGS 3 +#endif /* * When building perf, unistd.h is overridden. __NR_bpf is @@ -46,7 +56,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 +425,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