Received: by 10.223.176.46 with SMTP id f43csp1397846wra; Wed, 24 Jan 2018 16:08:18 -0800 (PST) X-Google-Smtp-Source: AH8x226oBUhzbrFhXVS82ekxYoKFhx5RXrd6jdPQ6Y46eUrNrY4yuMDfrq0eyLo2dLQeYWg9yWmj X-Received: by 10.101.88.138 with SMTP id d10mr12348311pgu.52.1516838898736; Wed, 24 Jan 2018 16:08:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516838898; cv=none; d=google.com; s=arc-20160816; b=EP7y2Iih954bNKidzZsYpquQa1o9czwF6KycersKFpr1KcD0iBBtqG4+241QXU8C/D bltIzv3YGZrW6CgEOU0KPiZtrFTGaR1rxDKt7X4NgANZB3hzSbxFFVllMgdWIGu0ponv JAmcgZAqW7NQq29/RCEiGYF84lEcns22dB1nNyMEIxSNy89apQ6nw9RMW4kzghJp+/40 iuSBcfguxE9hSnnv7IRgoAEKt7uRSGMBHdRfo+Cviq5hMCEO3jWi6kwDdSWJ0EuuwuCP zOzMOcf8mhf2r8Y5qAsj9enDCh3k4KAo8JVKqTQJCGIuCqypoljtP4vUeNSe1nOw+qXx xYCg== 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=IcfwoOnJvLVxx/ifKjXpi0WDKBgqn5y45uOPnAIqKK4=; b=QbsFtgsVzCg7d3V9OJdqGl4sgQzm9S7KFy0rfpa3TTeTOaajgEDLoF9kJHFiodCP2G PI1TPxs0wBjd0oipWEc1MzDHSy5oFn2P0yirp0c6UEtu9dk3ozShL2+sBK4YH8vXyBCg r1BY/1ynzsxuSWwUDDjXu6NzreNRVlMclVRrKlxg6c5NWVqiwOzCKkNHyHKSKjThnTmo P5wFmNW2zDsHVxAFBkwKpwoZQzb4f4hLErJ712avYGzVHvYC+qK0jEgTP5dlcqRkoUZA +zwXvbxZnF0wysaW2OcAS5NgD0qUcP60CJK8+K0sOBy3LIOmBebSXi0YMvIXywDKQKjf kANg== 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 e68si3659270pfa.298.2018.01.24.16.08.04; Wed, 24 Jan 2018 16:08:18 -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 S933034AbeAYAGL (ORCPT + 99 others); Wed, 24 Jan 2018 19:06:11 -0500 Received: from home.regit.org ([37.187.126.138]:58498 "EHLO home.regit.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932935AbeAYAGJ (ORCPT ); Wed, 24 Jan 2018 19:06:09 -0500 Received: from [2a01:e35:2fb6:1160:f022:11:465e:d69b] (helo=ice-age2.regit.org) by home.regit.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1eeV3O-0006oT-6w; Thu, 25 Jan 2018 01:06:07 +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 v7 2/5] libbpf: add function to setup XDP Date: Thu, 25 Jan 2018 01:05:45 +0100 Message-Id: <20180125000548.12320-3-eric@regit.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180125000548.12320-1-eric@regit.org> References: <4dc597a1-5046-3805-eb81-03a23bf0acbb@iogearbox.net> <20180125000548.12320-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 | 127 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.c | 2 + tools/lib/bpf/libbpf.h | 4 ++ 3 files changed, 133 insertions(+) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 5128677e4117..749a447ec9ed 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -25,6 +25,17 @@ #include #include #include "bpf.h" +#include "libbpf.h" +#include "nlattr.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 +57,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 +426,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