Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Browse files Browse the repository at this point in the history
Alexei Starovoitov says:

====================
pull-request: bpf 2018-02-02

The following pull-request contains BPF updates for your *net* tree.

The main changes are:

1) support XDP attach in libbpf, from Eric.

2) minor fixes, from Daniel, Jakub, Yonghong, Alexei.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 4, 2018
2 parents 3527799 + 09c0656 commit a6b8881
Show file tree
Hide file tree
Showing 28 changed files with 1,716 additions and 141 deletions.
31 changes: 31 additions & 0 deletions Documentation/bpf/bpf_devel_QA.txt
Original file line number Diff line number Diff line change
Expand Up @@ -516,4 +516,35 @@ A: LLVM has a -mcpu selector for the BPF back end in order to allow the
By the way, the BPF kernel selftests run with -mcpu=probe for better
test coverage.

Q: In some cases clang flag "-target bpf" is used but in other cases the
default clang target, which matches the underlying architecture, is used.
What is the difference and when I should use which?

A: Although LLVM IR generation and optimization try to stay architecture
independent, "-target <arch>" still has some impact on generated code:

- BPF program may recursively include header file(s) with file scope
inline assembly codes. The default target can handle this well,
while bpf target may fail if bpf backend assembler does not
understand these assembly codes, which is true in most cases.

- When compiled without -g, additional elf sections, e.g.,
.eh_frame and .rela.eh_frame, may be present in the object file
with default target, but not with bpf target.

- The default target may turn a C switch statement into a switch table
lookup and jump operation. Since the switch table is placed
in the global readonly section, the bpf program will fail to load.
The bpf target does not support switch table optimization.
The clang option "-fno-jump-tables" can be used to disable
switch table generation.

You should use default target when:

- Your program includes a header file, e.g., ptrace.h, which eventually
pulls in some header files containing file scope host assembly codes.
- You can add "-fno-jump-tables" to work around the switch table issue.

Otherwise, you can use bpf target.

Happy BPF hacking!
5 changes: 2 additions & 3 deletions drivers/net/netdevsim/bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,7 @@ static int
nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap)
{
struct nsim_bpf_bound_map *nmap;
unsigned int i;
int err;
int i, err;

if (WARN_ON(offmap->map.map_type != BPF_MAP_TYPE_ARRAY &&
offmap->map.map_type != BPF_MAP_TYPE_HASH))
Expand Down Expand Up @@ -518,7 +517,7 @@ nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap)
return 0;

err_free:
while (--i) {
while (--i >= 0) {
kfree(nmap->entry[i].key);
kfree(nmap->entry[i].value);
}
Expand Down
6 changes: 6 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -3228,6 +3228,12 @@ static inline int netif_set_real_num_rx_queues(struct net_device *dev,
}
#endif

static inline struct netdev_rx_queue *
__netif_get_rx_queue(struct net_device *dev, unsigned int rxq)
{
return dev->_rx + rxq;
}

#ifdef CONFIG_SYSFS
static inline unsigned int get_netdev_rx_queue_index(
struct netdev_rx_queue *queue)
Expand Down
32 changes: 24 additions & 8 deletions kernel/bpf/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1576,25 +1576,41 @@ int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
__u32 __user *prog_ids, u32 cnt)
{
struct bpf_prog **prog;
u32 i = 0, id;

unsigned long err = 0;
u32 i = 0, *ids;
bool nospc;

/* users of this function are doing:
* cnt = bpf_prog_array_length();
* if (cnt > 0)
* bpf_prog_array_copy_to_user(..., cnt);
* so below kcalloc doesn't need extra cnt > 0 check, but
* bpf_prog_array_length() releases rcu lock and
* prog array could have been swapped with empty or larger array,
* so always copy 'cnt' prog_ids to the user.
* In a rare race the user will see zero prog_ids
*/
ids = kcalloc(cnt, sizeof(u32), GFP_USER);
if (!ids)
return -ENOMEM;
rcu_read_lock();
prog = rcu_dereference(progs)->progs;
for (; *prog; prog++) {
if (*prog == &dummy_bpf_prog.prog)
continue;
id = (*prog)->aux->id;
if (copy_to_user(prog_ids + i, &id, sizeof(id))) {
rcu_read_unlock();
return -EFAULT;
}
ids[i] = (*prog)->aux->id;
if (++i == cnt) {
prog++;
break;
}
}
nospc = !!(*prog);
rcu_read_unlock();
if (*prog)
err = copy_to_user(prog_ids, ids, cnt * sizeof(u32));
kfree(ids);
if (err)
return -EFAULT;
if (nospc)
return -ENOSPC;
return 0;
}
Expand Down
4 changes: 4 additions & 0 deletions net/bpf/test_run.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
{
u32 size = kattr->test.data_size_in;
u32 repeat = kattr->test.repeat;
struct netdev_rx_queue *rxqueue;
struct xdp_buff xdp = {};
u32 retval, duration;
void *data;
Expand All @@ -165,6 +166,9 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
xdp.data_meta = xdp.data;
xdp.data_end = xdp.data + size;

rxqueue = __netif_get_rx_queue(current->nsproxy->net_ns->loopback_dev, 0);
xdp.rxq = &rxqueue->xdp_rxq;

retval = bpf_test_run(prog, &xdp, repeat, &duration);
if (xdp.data != data + XDP_PACKET_HEADROOM + NET_IP_ALIGN)
size = xdp.data_end - xdp.data;
Expand Down
2 changes: 1 addition & 1 deletion samples/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ hostprogs-y += xdp_rxq_info
hostprogs-y += syscall_tp

# Libbpf dependencies
LIBBPF := ../../tools/lib/bpf/bpf.o
LIBBPF := ../../tools/lib/bpf/bpf.o ../../tools/lib/bpf/nlattr.o
CGROUP_HELPERS := ../../tools/testing/selftests/bpf/cgroup_helpers.o

test_lru_dist-objs := test_lru_dist.o $(LIBBPF)
Expand Down
102 changes: 0 additions & 102 deletions samples/bpf/bpf_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,105 +695,3 @@ struct ksym *ksym_search(long key)
return &syms[0];
}

int 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;

memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;

sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sock < 0) {
printf("open netlink socket: %s\n", strerror(errno));
return -1;
}

if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
printf("bind to netlink: %s\n", strerror(errno));
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 | 43/*IFLA_XDP*/;
nla->nla_len = NLA_HDRLEN;

/* add XDP fd */
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
nla_xdp->nla_type = 1/*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 = 3/*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) {
printf("send to netlink: %s\n", strerror(errno));
goto cleanup;
}

len = recv(sock, buf, sizeof(buf), 0);
if (len < 0) {
printf("recv from netlink: %s\n", strerror(errno));
goto cleanup;
}

for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
nh = NLMSG_NEXT(nh, len)) {
if (nh->nlmsg_pid != getpid()) {
printf("Wrong pid %d, expected %d\n",
nh->nlmsg_pid, getpid());
goto cleanup;
}
if (nh->nlmsg_seq != seq) {
printf("Wrong seq %d, expected %d\n",
nh->nlmsg_seq, seq);
goto cleanup;
}
switch (nh->nlmsg_type) {
case NLMSG_ERROR:
err = (struct nlmsgerr *)NLMSG_DATA(nh);
if (!err->error)
continue;
printf("nlmsg error %s\n", strerror(-err->error));
goto cleanup;
case NLMSG_DONE:
break;
}
}

ret = 0;

cleanup:
close(sock);
return ret;
}
2 changes: 1 addition & 1 deletion samples/bpf/bpf_load.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,5 @@ struct ksym {

int load_kallsyms(void);
struct ksym *ksym_search(long key);
int set_link_xdp_fd(int ifindex, int fd, __u32 flags);
int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
#endif
4 changes: 2 additions & 2 deletions samples/bpf/xdp1_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ static __u32 xdp_flags;

static void int_exit(int sig)
{
set_link_xdp_fd(ifindex, -1, xdp_flags);
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
exit(0);
}

Expand Down Expand Up @@ -116,7 +116,7 @@ int main(int argc, char **argv)
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);

if (set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) {
if (bpf_set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) {
printf("link set xdp fd failed\n");
return 1;
}
Expand Down
6 changes: 3 additions & 3 deletions samples/bpf/xdp_redirect_cpu_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static const char *__doc__ =

/* Wanted to get rid of bpf_load.h and fake-"libbpf.h" (and instead
* use bpf/libbpf.h), but cannot as (currently) needed for XDP
* attaching to a device via set_link_xdp_fd()
* attaching to a device via bpf_set_link_xdp_fd()
*/
#include "libbpf.h"
#include "bpf_load.h"
Expand Down Expand Up @@ -67,7 +67,7 @@ static void int_exit(int sig)
"Interrupted: Removing XDP program on ifindex:%d device:%s\n",
ifindex, ifname);
if (ifindex > -1)
set_link_xdp_fd(ifindex, -1, xdp_flags);
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
exit(EXIT_OK);
}

Expand Down Expand Up @@ -682,7 +682,7 @@ int main(int argc, char **argv)
/* Remove XDP program when program is interrupted */
signal(SIGINT, int_exit);

if (set_link_xdp_fd(ifindex, prog_fd[prog_num], xdp_flags) < 0) {
if (bpf_set_link_xdp_fd(ifindex, prog_fd[prog_num], xdp_flags) < 0) {
fprintf(stderr, "link set xdp fd failed\n");
return EXIT_FAIL_XDP;
}
Expand Down
8 changes: 4 additions & 4 deletions samples/bpf/xdp_redirect_map_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ static __u32 xdp_flags;

static void int_exit(int sig)
{
set_link_xdp_fd(ifindex_in, -1, xdp_flags);
bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
if (ifindex_out_xdp_dummy_attached)
set_link_xdp_fd(ifindex_out, -1, xdp_flags);
bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
exit(0);
}

Expand Down Expand Up @@ -120,13 +120,13 @@ int main(int argc, char **argv)
return 1;
}

if (set_link_xdp_fd(ifindex_in, prog_fd[0], xdp_flags) < 0) {
if (bpf_set_link_xdp_fd(ifindex_in, prog_fd[0], xdp_flags) < 0) {
printf("ERROR: link set xdp fd failed on %d\n", ifindex_in);
return 1;
}

/* Loading dummy XDP prog on out-device */
if (set_link_xdp_fd(ifindex_out, prog_fd[1],
if (bpf_set_link_xdp_fd(ifindex_out, prog_fd[1],
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
ifindex_out_xdp_dummy_attached = false;
Expand Down
8 changes: 4 additions & 4 deletions samples/bpf/xdp_redirect_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ static __u32 xdp_flags;

static void int_exit(int sig)
{
set_link_xdp_fd(ifindex_in, -1, xdp_flags);
bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
if (ifindex_out_xdp_dummy_attached)
set_link_xdp_fd(ifindex_out, -1, xdp_flags);
bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
exit(0);
}

Expand Down Expand Up @@ -114,13 +114,13 @@ int main(int argc, char **argv)
return 1;
}

if (set_link_xdp_fd(ifindex_in, prog_fd[0], xdp_flags) < 0) {
if (bpf_set_link_xdp_fd(ifindex_in, prog_fd[0], xdp_flags) < 0) {
printf("ERROR: link set xdp fd failed on %d\n", ifindex_in);
return 1;
}

/* Loading dummy XDP prog on out-device */
if (set_link_xdp_fd(ifindex_out, prog_fd[1],
if (bpf_set_link_xdp_fd(ifindex_out, prog_fd[1],
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
ifindex_out_xdp_dummy_attached = false;
Expand Down
Loading

0 comments on commit a6b8881

Please sign in to comment.