Netdev List
 help / color / mirror / Atom feed
* [PATCHv5 perf/core 5/5] samples/bpf: Move open_raw_sock to separate header
From: Joe Stringer @ 2016-12-16 18:32 UTC (permalink / raw)
  To: acme; +Cc: linux-kernel, netdev, wangnan0, ast, daniel
In-Reply-To: <20161216183259.14840-1-joe@ovn.org>

This function was declared in libbpf.c and was the only remaining
function in this library, but has nothing to do with BPF. Shift it out
into a new header, sock_example.h, and include it from the relevant
samples.

Signed-off-by: Joe Stringer <joe@ovn.org>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/20161209024620.31660-8-joe@ovn.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
v5: No change.
---
 samples/bpf/Makefile                     | 2 +-
 samples/bpf/fds_example.c                | 1 +
 samples/bpf/libbpf.h                     | 3 ---
 samples/bpf/sock_example.c               | 1 +
 samples/bpf/{libbpf.c => sock_example.h} | 3 +--
 samples/bpf/sockex1_user.c               | 1 +
 samples/bpf/sockex2_user.c               | 1 +
 samples/bpf/sockex3_user.c               | 1 +
 8 files changed, 7 insertions(+), 6 deletions(-)
 rename samples/bpf/{libbpf.c => sock_example.h} (92%)

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 5a73f5a7ace1..f01b66f277b0 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -36,7 +36,7 @@ hostprogs-y += lwt_len_hist
 hostprogs-y += xdp_tx_iptunnel
 
 # Libbpf dependencies
-LIBBPF := libbpf.o ../../tools/lib/bpf/bpf.o
+LIBBPF := ../../tools/lib/bpf/bpf.o
 
 test_lru_dist-objs := test_lru_dist.o $(LIBBPF)
 sock_example-objs := sock_example.o $(LIBBPF)
diff --git a/samples/bpf/fds_example.c b/samples/bpf/fds_example.c
index 6245062844d1..92592e38569b 100644
--- a/samples/bpf/fds_example.c
+++ b/samples/bpf/fds_example.c
@@ -14,6 +14,7 @@
 
 #include "bpf_load.h"
 #include "libbpf.h"
+#include "sock_example.h"
 
 #define BPF_F_PIN	(1 << 0)
 #define BPF_F_GET	(1 << 1)
diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h
index 09aedc320009..3705fba453a0 100644
--- a/samples/bpf/libbpf.h
+++ b/samples/bpf/libbpf.h
@@ -185,7 +185,4 @@ struct bpf_insn;
 		.off   = 0,					\
 		.imm   = 0 })
 
-/* create RAW socket and bind to interface 'name' */
-int open_raw_sock(const char *name);
-
 #endif
diff --git a/samples/bpf/sock_example.c b/samples/bpf/sock_example.c
index 5546f8aac37e..6fc6e193ef1b 100644
--- a/samples/bpf/sock_example.c
+++ b/samples/bpf/sock_example.c
@@ -27,6 +27,7 @@
 #include <linux/ip.h>
 #include <stddef.h>
 #include "libbpf.h"
+#include "sock_example.h"
 
 char bpf_log_buf[BPF_LOG_BUF_SIZE];
 
diff --git a/samples/bpf/libbpf.c b/samples/bpf/sock_example.h
similarity index 92%
rename from samples/bpf/libbpf.c
rename to samples/bpf/sock_example.h
index bee473a494f1..09f7fe7e5fd7 100644
--- a/samples/bpf/libbpf.c
+++ b/samples/bpf/sock_example.h
@@ -1,4 +1,3 @@
-/* eBPF mini library */
 #include <stdlib.h>
 #include <stdio.h>
 #include <linux/unistd.h>
@@ -11,7 +10,7 @@
 #include <arpa/inet.h>
 #include "libbpf.h"
 
-int open_raw_sock(const char *name)
+static inline int open_raw_sock(const char *name)
 {
 	struct sockaddr_ll sll;
 	int sock;
diff --git a/samples/bpf/sockex1_user.c b/samples/bpf/sockex1_user.c
index 9454448bf198..6cd2feb3e9b3 100644
--- a/samples/bpf/sockex1_user.c
+++ b/samples/bpf/sockex1_user.c
@@ -3,6 +3,7 @@
 #include <linux/bpf.h>
 #include "libbpf.h"
 #include "bpf_load.h"
+#include "sock_example.h"
 #include <unistd.h>
 #include <arpa/inet.h>
 
diff --git a/samples/bpf/sockex2_user.c b/samples/bpf/sockex2_user.c
index 6a40600d5a83..0e0207c90841 100644
--- a/samples/bpf/sockex2_user.c
+++ b/samples/bpf/sockex2_user.c
@@ -3,6 +3,7 @@
 #include <linux/bpf.h>
 #include "libbpf.h"
 #include "bpf_load.h"
+#include "sock_example.h"
 #include <unistd.h>
 #include <arpa/inet.h>
 #include <sys/resource.h>
diff --git a/samples/bpf/sockex3_user.c b/samples/bpf/sockex3_user.c
index 9099c4255f23..b5524d417eb5 100644
--- a/samples/bpf/sockex3_user.c
+++ b/samples/bpf/sockex3_user.c
@@ -3,6 +3,7 @@
 #include <linux/bpf.h>
 #include "libbpf.h"
 #include "bpf_load.h"
+#include "sock_example.h"
 #include <unistd.h>
 #include <arpa/inet.h>
 #include <sys/resource.h>
-- 
2.10.2

^ permalink raw reply related

* [PATCHv5 perf/core 3/5] tools lib bpf: Add bpf_prog_{attach,detach}
From: Joe Stringer @ 2016-12-16 18:32 UTC (permalink / raw)
  To: acme; +Cc: linux-kernel, netdev, wangnan0, ast, daniel
In-Reply-To: <20161216183259.14840-1-joe@ovn.org>

Commit d8c5b17f2bc0 ("samples: bpf: add userspace example for attaching
eBPF programs to cgroups") added these functions to samples/libbpf, but
during this merge all of the samples libbpf functionality is shifting to
tools/lib/bpf. Shift these functions there.

Signed-off-by: Joe Stringer <joe@ovn.org>
---
v5: No change.
---
 samples/bpf/libbpf.c | 21 ---------------------
 samples/bpf/libbpf.h |  3 ---
 tools/lib/bpf/bpf.c  | 21 +++++++++++++++++++++
 tools/lib/bpf/bpf.h  |  3 +++
 4 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/samples/bpf/libbpf.c b/samples/bpf/libbpf.c
index 3391225ad7e9..d9af876b4a2c 100644
--- a/samples/bpf/libbpf.c
+++ b/samples/bpf/libbpf.c
@@ -11,27 +11,6 @@
 #include <arpa/inet.h>
 #include "libbpf.h"
 
-int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
-{
-	union bpf_attr attr = {
-		.target_fd = target_fd,
-		.attach_bpf_fd = prog_fd,
-		.attach_type = type,
-	};
-
-	return syscall(__NR_bpf, BPF_PROG_ATTACH, &attr, sizeof(attr));
-}
-
-int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
-{
-	union bpf_attr attr = {
-		.target_fd = target_fd,
-		.attach_type = type,
-	};
-
-	return syscall(__NR_bpf, BPF_PROG_DETACH, &attr, sizeof(attr));
-}
-
 int open_raw_sock(const char *name)
 {
 	struct sockaddr_ll sll;
diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h
index cf7d2386d1f9..cc815624aacf 100644
--- a/samples/bpf/libbpf.h
+++ b/samples/bpf/libbpf.h
@@ -6,9 +6,6 @@
 
 struct bpf_insn;
 
-int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type);
-int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
-
 /* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
 
 #define BPF_ALU64_REG(OP, DST, SRC)				\
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index d0afb26c2e0f..e19335df0d3a 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -167,3 +167,24 @@ int bpf_obj_get(const char *pathname)
 
 	return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
 }
+
+int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
+{
+	union bpf_attr attr = {
+		.target_fd = target_fd,
+		.attach_bpf_fd = prog_fd,
+		.attach_type = type,
+	};
+
+	return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
+}
+
+int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
+{
+	union bpf_attr attr = {
+		.target_fd = target_fd,
+		.attach_type = type,
+	};
+
+	return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 7fcdce16fd62..a2f9853dd882 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -41,5 +41,8 @@ int bpf_map_delete_elem(int fd, void *key);
 int bpf_map_get_next_key(int fd, void *key, void *next_key);
 int bpf_obj_pin(int fd, const char *pathname);
 int bpf_obj_get(const char *pathname);
+int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type);
+int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
+
 
 #endif
-- 
2.10.2

^ permalink raw reply related

* [PATCHv5 perf/core 2/5] samples/bpf: Switch over to libbpf
From: Joe Stringer @ 2016-12-16 18:32 UTC (permalink / raw)
  To: acme; +Cc: linux-kernel, netdev, wangnan0, ast, daniel
In-Reply-To: <20161216183259.14840-1-joe@ovn.org>

Now that libbpf under tools/lib/bpf/* is synced with the version from
samples/bpf, we can get rid most of the libbpf library here.

Committer notes:

Tested it the same way as the previous patch in this series.

Signed-off-by: Joe Stringer <joe@ovn.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: netdev@vger.kernel.org
Link: http://lkml.kernel.org/r/20161214224342.12858-3-joe@ovn.org
[ Use -I$(srctree)/tools/lib/ to support out of source code tree builds, as noticed by Wang Nan ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
v5: Joe - I took acme's version from his branch tmp.perf/samples-libbpf and
    applied an incremental fix for the discrepancy between the
    bpf_load_program() API - samples/ was using program size while libbpf uses
    instruction count.
---
 samples/bpf/Makefile             |  68 +++++++++++++-----------
 samples/bpf/README.rst           |   4 +-
 samples/bpf/bpf_load.c           |   3 +-
 samples/bpf/fds_example.c        |   3 +-
 samples/bpf/libbpf.c             | 111 ---------------------------------------
 samples/bpf/libbpf.h             |  19 +------
 samples/bpf/sock_example.c       |   3 +-
 samples/bpf/test_cgrp2_attach.c  |   3 +-
 samples/bpf/test_cgrp2_attach2.c |   3 +-
 samples/bpf/test_cgrp2_sock.c    |   3 +-
 10 files changed, 52 insertions(+), 168 deletions(-)

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index f2219c1489e5..81b0ef2f7994 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -35,40 +35,43 @@ hostprogs-y += tc_l2_redirect
 hostprogs-y += lwt_len_hist
 hostprogs-y += xdp_tx_iptunnel
 
-test_lru_dist-objs := test_lru_dist.o libbpf.o
-sock_example-objs := sock_example.o libbpf.o
-fds_example-objs := bpf_load.o libbpf.o fds_example.o
-sockex1-objs := bpf_load.o libbpf.o sockex1_user.o
-sockex2-objs := bpf_load.o libbpf.o sockex2_user.o
-sockex3-objs := bpf_load.o libbpf.o sockex3_user.o
-tracex1-objs := bpf_load.o libbpf.o tracex1_user.o
-tracex2-objs := bpf_load.o libbpf.o tracex2_user.o
-tracex3-objs := bpf_load.o libbpf.o tracex3_user.o
-tracex4-objs := bpf_load.o libbpf.o tracex4_user.o
-tracex5-objs := bpf_load.o libbpf.o tracex5_user.o
-tracex6-objs := bpf_load.o libbpf.o tracex6_user.o
-test_probe_write_user-objs := bpf_load.o libbpf.o test_probe_write_user_user.o
-trace_output-objs := bpf_load.o libbpf.o trace_output_user.o
-lathist-objs := bpf_load.o libbpf.o lathist_user.o
-offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o
-spintest-objs := bpf_load.o libbpf.o spintest_user.o
-map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o
-test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o
-test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o
-test_cgrp2_attach-objs := libbpf.o test_cgrp2_attach.o
-test_cgrp2_attach2-objs := libbpf.o test_cgrp2_attach2.o cgroup_helpers.o
-test_cgrp2_sock-objs := libbpf.o test_cgrp2_sock.o
-test_cgrp2_sock2-objs := bpf_load.o libbpf.o test_cgrp2_sock2.o
-xdp1-objs := bpf_load.o libbpf.o xdp1_user.o
+# Libbpf dependencies
+LIBBPF := libbpf.o ../../tools/lib/bpf/bpf.o
+
+test_lru_dist-objs := test_lru_dist.o $(LIBBPF)
+sock_example-objs := sock_example.o $(LIBBPF)
+fds_example-objs := bpf_load.o $(LIBBPF) fds_example.o
+sockex1-objs := bpf_load.o $(LIBBPF) sockex1_user.o
+sockex2-objs := bpf_load.o $(LIBBPF) sockex2_user.o
+sockex3-objs := bpf_load.o $(LIBBPF) sockex3_user.o
+tracex1-objs := bpf_load.o $(LIBBPF) tracex1_user.o
+tracex2-objs := bpf_load.o $(LIBBPF) tracex2_user.o
+tracex3-objs := bpf_load.o $(LIBBPF) tracex3_user.o
+tracex4-objs := bpf_load.o $(LIBBPF) tracex4_user.o
+tracex5-objs := bpf_load.o $(LIBBPF) tracex5_user.o
+tracex6-objs := bpf_load.o $(LIBBPF) tracex6_user.o
+test_probe_write_user-objs := bpf_load.o $(LIBBPF) test_probe_write_user_user.o
+trace_output-objs := bpf_load.o $(LIBBPF) trace_output_user.o
+lathist-objs := bpf_load.o $(LIBBPF) lathist_user.o
+offwaketime-objs := bpf_load.o $(LIBBPF) offwaketime_user.o
+spintest-objs := bpf_load.o $(LIBBPF) spintest_user.o
+map_perf_test-objs := bpf_load.o $(LIBBPF) map_perf_test_user.o
+test_overhead-objs := bpf_load.o $(LIBBPF) test_overhead_user.o
+test_cgrp2_array_pin-objs := $(LIBBPF) test_cgrp2_array_pin.o
+test_cgrp2_attach-objs := $(LIBBPF) test_cgrp2_attach.o
+test_cgrp2_attach2-objs := $(LIBBPF) test_cgrp2_attach2.o cgroup_helpers.o
+test_cgrp2_sock-objs := $(LIBBPF) test_cgrp2_sock.o
+test_cgrp2_sock2-objs := bpf_load.o $(LIBBPF) test_cgrp2_sock2.o
+xdp1-objs := bpf_load.o $(LIBBPF) xdp1_user.o
 # reuse xdp1 source intentionally
-xdp2-objs := bpf_load.o libbpf.o xdp1_user.o
-test_current_task_under_cgroup-objs := bpf_load.o libbpf.o cgroup_helpers.o \
+xdp2-objs := bpf_load.o $(LIBBPF) xdp1_user.o
+test_current_task_under_cgroup-objs := bpf_load.o $(LIBBPF) cgroup_helpers.o \
 				       test_current_task_under_cgroup_user.o
-trace_event-objs := bpf_load.o libbpf.o trace_event_user.o
-sampleip-objs := bpf_load.o libbpf.o sampleip_user.o
-tc_l2_redirect-objs := bpf_load.o libbpf.o tc_l2_redirect_user.o
-lwt_len_hist-objs := bpf_load.o libbpf.o lwt_len_hist_user.o
-xdp_tx_iptunnel-objs := bpf_load.o libbpf.o xdp_tx_iptunnel_user.o
+trace_event-objs := bpf_load.o $(LIBBPF) trace_event_user.o
+sampleip-objs := bpf_load.o $(LIBBPF) sampleip_user.o
+tc_l2_redirect-objs := bpf_load.o $(LIBBPF) tc_l2_redirect_user.o
+lwt_len_hist-objs := bpf_load.o $(LIBBPF) lwt_len_hist_user.o
+xdp_tx_iptunnel-objs := bpf_load.o $(LIBBPF) xdp_tx_iptunnel_user.o
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
@@ -104,6 +107,7 @@ always += lwt_len_hist_kern.o
 always += xdp_tx_iptunnel_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
+HOSTCFLAGS += -I$(srctree)/tools/lib/
 HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/
 
 HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable
diff --git a/samples/bpf/README.rst b/samples/bpf/README.rst
index a43eae3f0551..79f9a58f1872 100644
--- a/samples/bpf/README.rst
+++ b/samples/bpf/README.rst
@@ -1,8 +1,8 @@
 eBPF sample programs
 ====================
 
-This directory contains a mini eBPF library, test stubs, verifier
-test-suite and examples for using eBPF.
+This directory contains a test stubs, verifier test-suite and examples
+for using eBPF. The examples use libbpf from tools/lib/bpf.
 
 Build dependencies
 ==================
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index f5b186c46b7c..1bfb43394013 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -66,6 +66,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 	bool is_perf_event = strncmp(event, "perf_event", 10) == 0;
 	bool is_cgroup_skb = strncmp(event, "cgroup/skb", 10) == 0;
 	bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0;
+	size_t insns_cnt = size / sizeof(struct bpf_insn);
 	enum bpf_prog_type prog_type;
 	char buf[256];
 	int fd, efd, err, id;
@@ -95,7 +96,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 		return -1;
 	}
 
-	fd = bpf_load_program(prog_type, prog, size, license, kern_version,
+	fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version,
 			      bpf_log_buf, BPF_LOG_BUF_SIZE);
 	if (fd < 0) {
 		printf("bpf_load_program() err=%d\n%s", errno, bpf_log_buf);
diff --git a/samples/bpf/fds_example.c b/samples/bpf/fds_example.c
index 8a4fc4ef3993..6245062844d1 100644
--- a/samples/bpf/fds_example.c
+++ b/samples/bpf/fds_example.c
@@ -53,13 +53,14 @@ static int bpf_prog_create(const char *object)
 		BPF_MOV64_IMM(BPF_REG_0, 1),
 		BPF_EXIT_INSN(),
 	};
+	size_t insns_cnt = sizeof(insns) / sizeof(struct bpf_insn);
 
 	if (object) {
 		assert(!load_bpf_file((char *)object));
 		return prog_fd[0];
 	} else {
 		return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER,
-					insns, sizeof(insns), "GPL", 0,
+					insns, insns_cnt, "GPL", 0,
 					bpf_log_buf, BPF_LOG_BUF_SIZE);
 	}
 }
diff --git a/samples/bpf/libbpf.c b/samples/bpf/libbpf.c
index 6f076abdca35..3391225ad7e9 100644
--- a/samples/bpf/libbpf.c
+++ b/samples/bpf/libbpf.c
@@ -4,8 +4,6 @@
 #include <linux/unistd.h>
 #include <unistd.h>
 #include <string.h>
-#include <linux/netlink.h>
-#include <linux/bpf.h>
 #include <errno.h>
 #include <net/ethernet.h>
 #include <net/if.h>
@@ -13,96 +11,6 @@
 #include <arpa/inet.h>
 #include "libbpf.h"
 
-static __u64 ptr_to_u64(void *ptr)
-{
-	return (__u64) (unsigned long) ptr;
-}
-
-int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
-		   int max_entries, int map_flags)
-{
-	union bpf_attr attr = {
-		.map_type = map_type,
-		.key_size = key_size,
-		.value_size = value_size,
-		.max_entries = max_entries,
-		.map_flags = map_flags,
-	};
-
-	return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
-}
-
-int bpf_map_update_elem(int fd, void *key, void *value, unsigned long long flags)
-{
-	union bpf_attr attr = {
-		.map_fd = fd,
-		.key = ptr_to_u64(key),
-		.value = ptr_to_u64(value),
-		.flags = flags,
-	};
-
-	return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
-}
-
-int bpf_map_lookup_elem(int fd, void *key, void *value)
-{
-	union bpf_attr attr = {
-		.map_fd = fd,
-		.key = ptr_to_u64(key),
-		.value = ptr_to_u64(value),
-	};
-
-	return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
-}
-
-int bpf_map_delete_elem(int fd, void *key)
-{
-	union bpf_attr attr = {
-		.map_fd = fd,
-		.key = ptr_to_u64(key),
-	};
-
-	return syscall(__NR_bpf, BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
-}
-
-int bpf_map_get_next_key(int fd, void *key, void *next_key)
-{
-	union bpf_attr attr = {
-		.map_fd = fd,
-		.key = ptr_to_u64(key),
-		.next_key = ptr_to_u64(next_key),
-	};
-
-	return syscall(__NR_bpf, BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
-}
-
-#define ROUND_UP(x, n) (((x) + (n) - 1u) & ~((n) - 1u))
-
-int bpf_load_program(enum bpf_prog_type prog_type,
-		     const struct bpf_insn *insns, int prog_len,
-		     const char *license, int kern_version,
-		     char *log_buf, size_t log_buf_sz)
-{
-	union bpf_attr attr = {
-		.prog_type = prog_type,
-		.insns = ptr_to_u64((void *) insns),
-		.insn_cnt = prog_len / sizeof(struct bpf_insn),
-		.license = ptr_to_u64((void *) license),
-		.log_buf = ptr_to_u64(log_buf),
-		.log_size = log_buf_sz,
-		.log_level = 1,
-	};
-
-	/* assign one field outside of struct init to make sure any
-	 * padding is zero initialized
-	 */
-	attr.kern_version = kern_version;
-
-	log_buf[0] = 0;
-
-	return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
-}
-
 int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
 {
 	union bpf_attr attr = {
@@ -124,25 +32,6 @@ int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
 	return syscall(__NR_bpf, BPF_PROG_DETACH, &attr, sizeof(attr));
 }
 
-int bpf_obj_pin(int fd, const char *pathname)
-{
-	union bpf_attr attr = {
-		.pathname	= ptr_to_u64((void *)pathname),
-		.bpf_fd		= fd,
-	};
-
-	return syscall(__NR_bpf, BPF_OBJ_PIN, &attr, sizeof(attr));
-}
-
-int bpf_obj_get(const char *pathname)
-{
-	union bpf_attr attr = {
-		.pathname	= ptr_to_u64((void *)pathname),
-	};
-
-	return syscall(__NR_bpf, BPF_OBJ_GET, &attr, sizeof(attr));
-}
-
 int open_raw_sock(const char *name)
 {
 	struct sockaddr_ll sll;
diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h
index 20e3457857ca..cf7d2386d1f9 100644
--- a/samples/bpf/libbpf.h
+++ b/samples/bpf/libbpf.h
@@ -2,28 +2,13 @@
 #ifndef __LIBBPF_H
 #define __LIBBPF_H
 
-struct bpf_insn;
-
-int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
-		   int max_entries, int map_flags);
-int bpf_map_update_elem(int fd, void *key, void *value, unsigned long long flags);
-int bpf_map_lookup_elem(int fd, void *key, void *value);
-int bpf_map_delete_elem(int fd, void *key);
-int bpf_map_get_next_key(int fd, void *key, void *next_key);
+#include <bpf/bpf.h>
 
-int bpf_load_program(enum bpf_prog_type prog_type,
-		     const struct bpf_insn *insns, int insn_len,
-		     const char *license, int kern_version,
-		     char *log_buf, size_t log_buf_sz);
+struct bpf_insn;
 
 int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type);
 int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
 
-int bpf_obj_pin(int fd, const char *pathname);
-int bpf_obj_get(const char *pathname);
-
-#define BPF_LOG_BUF_SIZE (256 * 1024)
-
 /* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
 
 #define BPF_ALU64_REG(OP, DST, SRC)				\
diff --git a/samples/bpf/sock_example.c b/samples/bpf/sock_example.c
index d6b91e9a38ad..5546f8aac37e 100644
--- a/samples/bpf/sock_example.c
+++ b/samples/bpf/sock_example.c
@@ -56,8 +56,9 @@ static int test_sock(void)
 		BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 */
 		BPF_EXIT_INSN(),
 	};
+	size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
 
-	prog_fd = bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog),
+	prog_fd = bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, insns_cnt,
 				   "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE);
 	if (prog_fd < 0) {
 		printf("failed to load prog '%s'\n", strerror(errno));
diff --git a/samples/bpf/test_cgrp2_attach.c b/samples/bpf/test_cgrp2_attach.c
index 8283ef86d392..504058631ffc 100644
--- a/samples/bpf/test_cgrp2_attach.c
+++ b/samples/bpf/test_cgrp2_attach.c
@@ -68,9 +68,10 @@ static int prog_load(int map_fd, int verdict)
 		BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
 		BPF_EXIT_INSN(),
 	};
+	size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
 
 	return bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB,
-				prog, sizeof(prog), "GPL", 0,
+				prog, insns_cnt, "GPL", 0,
 				bpf_log_buf, BPF_LOG_BUF_SIZE);
 }
 
diff --git a/samples/bpf/test_cgrp2_attach2.c b/samples/bpf/test_cgrp2_attach2.c
index fc6092fdc3b0..6e69be37f87f 100644
--- a/samples/bpf/test_cgrp2_attach2.c
+++ b/samples/bpf/test_cgrp2_attach2.c
@@ -41,9 +41,10 @@ static int prog_load(int verdict)
 		BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
 		BPF_EXIT_INSN(),
 	};
+	size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
 
 	ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB,
-			       prog, sizeof(prog), "GPL", 0,
+			       prog, insns_cnt, "GPL", 0,
 			       bpf_log_buf, BPF_LOG_BUF_SIZE);
 
 	if (ret < 0) {
diff --git a/samples/bpf/test_cgrp2_sock.c b/samples/bpf/test_cgrp2_sock.c
index 43b4bde5d05c..0791b949cbe4 100644
--- a/samples/bpf/test_cgrp2_sock.c
+++ b/samples/bpf/test_cgrp2_sock.c
@@ -35,8 +35,9 @@ static int prog_load(int idx)
 		BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
 		BPF_EXIT_INSN(),
 	};
+	size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
 
-	return bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, sizeof(prog),
+	return bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, insns_cnt,
 				"GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE);
 }
 
-- 
2.10.2

^ permalink raw reply related

* [PATCHv5 perf/core 1/5] samples/bpf: Make samples more libbpf-centric
From: Joe Stringer @ 2016-12-16 18:32 UTC (permalink / raw)
  To: acme; +Cc: linux-kernel, netdev, wangnan0, ast, daniel
In-Reply-To: <20161216183259.14840-1-joe@ovn.org>

Switch all of the sample code to use the function names from
tools/lib/bpf so that they're consistent with that, and to declare their
own log buffers. This allow the next commit to be purely devoted to
getting rid of the duplicate library in samples/bpf.

Committer notes:

Testing it:

On a fedora rawhide container, with clang/llvm 3.9, sharing the host
linux kernel git tree:

  # make O=/tmp/build/linux/ headers_install
  # make O=/tmp/build/linux -C samples/bpf/

Since I forgot to make it privileged, just tested it outside the
container, using what it generated:

  # uname -a
  Linux jouet 4.9.0-rc8+ #1 SMP Mon Dec 12 11:20:49 BRT 2016 x86_64 x86_64 x86_64 GNU/Linux
  # cd /var/lib/docker/devicemapper/mnt/c43e09a53ff56c86a07baf79847f00e2cc2a17a1e2220e1adbf8cbc62734feda/rootfs/tmp/build/linux/samples/bpf/
  # ls -la offwaketime
  -rwxr-xr-x. 1 root root 24200 Dec 15 12:19 offwaketime
  # file offwaketime
  offwaketime: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=c940d3f127d5e66cdd680e42d885cb0b64f8a0e4, not stripped
  # readelf -SW offwaketime_kern.o  | grep PROGBITS
  [ 2] .text             PROGBITS        0000000000000000 000040 000000 00  AX  0   0  4
  [ 3] kprobe/try_to_wake_up PROGBITS        0000000000000000 000040 0000d8 00  AX  0   0  8
  [ 5] tracepoint/sched/sched_switch PROGBITS        0000000000000000 000118 000318 00  AX  0   0  8
  [ 7] maps              PROGBITS        0000000000000000 000430 000050 00  WA  0   0  4
  [ 8] license           PROGBITS        0000000000000000 000480 000004 00  WA  0   0  1
  [ 9] version           PROGBITS        0000000000000000 000484 000004 00  WA  0   0  4
  # ./offwaketime | head -5
  swapper/1;start_secondary;cpu_startup_entry;schedule_preempt_disabled;schedule;__schedule;-;---;; 106
  CPU 0/KVM;entry_SYSCALL_64_fastpath;sys_ioctl;do_vfs_ioctl;kvm_vcpu_ioctl;kvm_arch_vcpu_ioctl_run;kvm_vcpu_block;schedule;__schedule;-;try_to_wake_up;swake_up_locked;swake_up;apic_timer_expired;apic_timer_fn;__hrtimer_run_queues;hrtimer_interrupt;local_apic_timer_interrupt;smp_apic_timer_interrupt;__irqentry_text_start;cpuidle_enter;call_cpuidle;cpu_startup_entry;start_secondary;;swapper/3 2
  Compositor;entry_SYSCALL_64_fastpath;sys_futex;do_futex;futex_wait;futex_wait_queue_me;schedule;__schedule;-;try_to_wake_up;futex_requeue;do_futex;sys_futex;entry_SYSCALL_64_fastpath;;SoftwareVsyncTh 5
  firefox;entry_SYSCALL_64_fastpath;sys_poll;do_sys_poll;poll_schedule_timeout;schedule_hrtimeout_range;schedule_hrtimeout_range_clock;schedule;__schedule;-;try_to_wake_up;pollwake;__wake_up_common;__wake_up_sync_key;pipe_write;__vfs_write;vfs_write;sys_write;entry_SYSCALL_64_fastpath;;Timer 13
  JS Helper;entry_SYSCALL_64_fastpath;sys_futex;do_futex;futex_wait;futex_wait_queue_me;schedule;__schedule;-;try_to_wake_up;do_futex;sys_futex;entry_SYSCALL_64_fastpath;;firefox 2
  #

Signed-off-by: Joe Stringer <joe@ovn.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: netdev@vger.kernel.org
Link: http://lkml.kernel.org/r/20161214224342.12858-2-joe@ovn.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
v5: No change.
---
 samples/bpf/bpf_load.c                            | 17 +++++++++---
 samples/bpf/bpf_load.h                            |  3 +++
 samples/bpf/fds_example.c                         |  9 ++++---
 samples/bpf/lathist_user.c                        |  2 +-
 samples/bpf/libbpf.c                              | 23 ++++++++--------
 samples/bpf/libbpf.h                              | 18 ++++++-------
 samples/bpf/lwt_len_hist_user.c                   |  6 +++--
 samples/bpf/offwaketime_user.c                    |  8 +++---
 samples/bpf/sampleip_user.c                       |  4 +--
 samples/bpf/sock_example.c                        | 12 +++++----
 samples/bpf/sockex1_user.c                        |  6 ++---
 samples/bpf/sockex2_user.c                        |  4 +--
 samples/bpf/sockex3_user.c                        |  4 +--
 samples/bpf/spintest_user.c                       |  8 +++---
 samples/bpf/tc_l2_redirect_user.c                 |  4 +--
 samples/bpf/test_cgrp2_array_pin.c                |  4 +--
 samples/bpf/test_cgrp2_attach.c                   | 11 +++++---
 samples/bpf/test_cgrp2_attach2.c                  |  7 +++--
 samples/bpf/test_cgrp2_sock.c                     |  6 +++--
 samples/bpf/test_current_task_under_cgroup_user.c |  8 +++---
 samples/bpf/test_lru_dist.c                       | 32 +++++++++++------------
 samples/bpf/test_probe_write_user_user.c          |  2 +-
 samples/bpf/trace_event_user.c                    | 14 +++++-----
 samples/bpf/trace_output_user.c                   |  2 +-
 samples/bpf/tracex2_user.c                        | 10 +++----
 samples/bpf/tracex3_user.c                        |  4 +--
 samples/bpf/tracex4_user.c                        |  4 +--
 samples/bpf/tracex6_user.c                        |  2 +-
 samples/bpf/xdp1_user.c                           |  2 +-
 samples/bpf/xdp_tx_iptunnel_user.c                |  6 ++---
 30 files changed, 133 insertions(+), 109 deletions(-)

diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index e30b6de94f2e..f5b186c46b7c 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -22,7 +22,6 @@
 #include <poll.h>
 #include <ctype.h>
 #include "libbpf.h"
-#include "bpf_helpers.h"
 #include "bpf_load.h"
 
 #define DEBUGFS "/sys/kernel/debug/tracing/"
@@ -30,17 +29,26 @@
 static char license[128];
 static int kern_version;
 static bool processed_sec[128];
+char bpf_log_buf[BPF_LOG_BUF_SIZE];
 int map_fd[MAX_MAPS];
 int prog_fd[MAX_PROGS];
 int event_fd[MAX_PROGS];
 int prog_cnt;
 int prog_array_fd = -1;
 
+struct bpf_map_def {
+	unsigned int type;
+	unsigned int key_size;
+	unsigned int value_size;
+	unsigned int max_entries;
+	unsigned int map_flags;
+};
+
 static int populate_prog_array(const char *event, int prog_fd)
 {
 	int ind = atoi(event), err;
 
-	err = bpf_update_elem(prog_array_fd, &ind, &prog_fd, BPF_ANY);
+	err = bpf_map_update_elem(prog_array_fd, &ind, &prog_fd, BPF_ANY);
 	if (err < 0) {
 		printf("failed to store prog_fd in prog_array\n");
 		return -1;
@@ -87,9 +95,10 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 		return -1;
 	}
 
-	fd = bpf_prog_load(prog_type, prog, size, license, kern_version);
+	fd = bpf_load_program(prog_type, prog, size, license, kern_version,
+			      bpf_log_buf, BPF_LOG_BUF_SIZE);
 	if (fd < 0) {
-		printf("bpf_prog_load() err=%d\n%s", errno, bpf_log_buf);
+		printf("bpf_load_program() err=%d\n%s", errno, bpf_log_buf);
 		return -1;
 	}
 
diff --git a/samples/bpf/bpf_load.h b/samples/bpf/bpf_load.h
index fb46a421ab41..c827827299b3 100644
--- a/samples/bpf/bpf_load.h
+++ b/samples/bpf/bpf_load.h
@@ -1,12 +1,15 @@
 #ifndef __BPF_LOAD_H
 #define __BPF_LOAD_H
 
+#include "libbpf.h"
+
 #define MAX_MAPS 32
 #define MAX_PROGS 32
 
 extern int map_fd[MAX_MAPS];
 extern int prog_fd[MAX_PROGS];
 extern int event_fd[MAX_PROGS];
+extern char bpf_log_buf[BPF_LOG_BUF_SIZE];
 extern int prog_cnt;
 
 /* parses elf file compiled by llvm .c->.o
diff --git a/samples/bpf/fds_example.c b/samples/bpf/fds_example.c
index 625e797be6ef..8a4fc4ef3993 100644
--- a/samples/bpf/fds_example.c
+++ b/samples/bpf/fds_example.c
@@ -58,8 +58,9 @@ static int bpf_prog_create(const char *object)
 		assert(!load_bpf_file((char *)object));
 		return prog_fd[0];
 	} else {
-		return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
-				     insns, sizeof(insns), "GPL", 0);
+		return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER,
+					insns, sizeof(insns), "GPL", 0,
+					bpf_log_buf, BPF_LOG_BUF_SIZE);
 	}
 }
 
@@ -83,12 +84,12 @@ static int bpf_do_map(const char *file, uint32_t flags, uint32_t key,
 	}
 
 	if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) {
-		ret = bpf_update_elem(fd, &key, &value, 0);
+		ret = bpf_map_update_elem(fd, &key, &value, 0);
 		printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value,
 		       ret, strerror(errno));
 		assert(ret == 0);
 	} else if (flags & BPF_F_KEY) {
-		ret = bpf_lookup_elem(fd, &key, &value);
+		ret = bpf_map_lookup_elem(fd, &key, &value);
 		printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value,
 		       ret, strerror(errno));
 		assert(ret == 0);
diff --git a/samples/bpf/lathist_user.c b/samples/bpf/lathist_user.c
index 65da8c1576de..6477bad5b4e2 100644
--- a/samples/bpf/lathist_user.c
+++ b/samples/bpf/lathist_user.c
@@ -73,7 +73,7 @@ static void get_data(int fd)
 	for (c = 0; c < MAX_CPU; c++) {
 		for (i = 0; i < MAX_ENTRIES; i++) {
 			key = c * MAX_ENTRIES + i;
-			bpf_lookup_elem(fd, &key, &value);
+			bpf_map_lookup_elem(fd, &key, &value);
 
 			cpu_hist[c].data[i] = value;
 			if (value > cpu_hist[c].max)
diff --git a/samples/bpf/libbpf.c b/samples/bpf/libbpf.c
index 9ce707bf02a7..6f076abdca35 100644
--- a/samples/bpf/libbpf.c
+++ b/samples/bpf/libbpf.c
@@ -32,7 +32,7 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
 	return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
 }
 
-int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
+int bpf_map_update_elem(int fd, void *key, void *value, unsigned long long flags)
 {
 	union bpf_attr attr = {
 		.map_fd = fd,
@@ -44,7 +44,7 @@ int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
 	return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
 }
 
-int bpf_lookup_elem(int fd, void *key, void *value)
+int bpf_map_lookup_elem(int fd, void *key, void *value)
 {
 	union bpf_attr attr = {
 		.map_fd = fd,
@@ -55,7 +55,7 @@ int bpf_lookup_elem(int fd, void *key, void *value)
 	return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
 }
 
-int bpf_delete_elem(int fd, void *key)
+int bpf_map_delete_elem(int fd, void *key)
 {
 	union bpf_attr attr = {
 		.map_fd = fd,
@@ -65,7 +65,7 @@ int bpf_delete_elem(int fd, void *key)
 	return syscall(__NR_bpf, BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
 }
 
-int bpf_get_next_key(int fd, void *key, void *next_key)
+int bpf_map_get_next_key(int fd, void *key, void *next_key)
 {
 	union bpf_attr attr = {
 		.map_fd = fd,
@@ -78,19 +78,18 @@ int bpf_get_next_key(int fd, void *key, void *next_key)
 
 #define ROUND_UP(x, n) (((x) + (n) - 1u) & ~((n) - 1u))
 
-char bpf_log_buf[LOG_BUF_SIZE];
-
-int bpf_prog_load(enum bpf_prog_type prog_type,
-		  const struct bpf_insn *insns, int prog_len,
-		  const char *license, int kern_version)
+int bpf_load_program(enum bpf_prog_type prog_type,
+		     const struct bpf_insn *insns, int prog_len,
+		     const char *license, int kern_version,
+		     char *log_buf, size_t log_buf_sz)
 {
 	union bpf_attr attr = {
 		.prog_type = prog_type,
 		.insns = ptr_to_u64((void *) insns),
 		.insn_cnt = prog_len / sizeof(struct bpf_insn),
 		.license = ptr_to_u64((void *) license),
-		.log_buf = ptr_to_u64(bpf_log_buf),
-		.log_size = LOG_BUF_SIZE,
+		.log_buf = ptr_to_u64(log_buf),
+		.log_size = log_buf_sz,
 		.log_level = 1,
 	};
 
@@ -99,7 +98,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
 	 */
 	attr.kern_version = kern_version;
 
-	bpf_log_buf[0] = 0;
+	log_buf[0] = 0;
 
 	return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
 }
diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h
index 94a901d86fc2..20e3457857ca 100644
--- a/samples/bpf/libbpf.h
+++ b/samples/bpf/libbpf.h
@@ -6,14 +6,15 @@ struct bpf_insn;
 
 int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
 		   int max_entries, int map_flags);
-int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags);
-int bpf_lookup_elem(int fd, void *key, void *value);
-int bpf_delete_elem(int fd, void *key);
-int bpf_get_next_key(int fd, void *key, void *next_key);
+int bpf_map_update_elem(int fd, void *key, void *value, unsigned long long flags);
+int bpf_map_lookup_elem(int fd, void *key, void *value);
+int bpf_map_delete_elem(int fd, void *key);
+int bpf_map_get_next_key(int fd, void *key, void *next_key);
 
-int bpf_prog_load(enum bpf_prog_type prog_type,
-		  const struct bpf_insn *insns, int insn_len,
-		  const char *license, int kern_version);
+int bpf_load_program(enum bpf_prog_type prog_type,
+		     const struct bpf_insn *insns, int insn_len,
+		     const char *license, int kern_version,
+		     char *log_buf, size_t log_buf_sz);
 
 int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type);
 int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
@@ -21,8 +22,7 @@ int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
 int bpf_obj_pin(int fd, const char *pathname);
 int bpf_obj_get(const char *pathname);
 
-#define LOG_BUF_SIZE (256 * 1024)
-extern char bpf_log_buf[LOG_BUF_SIZE];
+#define BPF_LOG_BUF_SIZE (256 * 1024)
 
 /* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
 
diff --git a/samples/bpf/lwt_len_hist_user.c b/samples/bpf/lwt_len_hist_user.c
index 05d783fc5daf..ec8f3bbcbef3 100644
--- a/samples/bpf/lwt_len_hist_user.c
+++ b/samples/bpf/lwt_len_hist_user.c
@@ -14,6 +14,8 @@
 #define MAX_INDEX 64
 #define MAX_STARS 38
 
+char bpf_log_buf[BPF_LOG_BUF_SIZE];
+
 static void stars(char *str, long val, long max, int width)
 {
 	int i;
@@ -41,13 +43,13 @@ int main(int argc, char **argv)
 		return -1;
 	}
 
-	while (bpf_get_next_key(map_fd, &key, &next_key) == 0) {
+	while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) {
 		if (next_key >= MAX_INDEX) {
 			fprintf(stderr, "Key %lu out of bounds\n", next_key);
 			continue;
 		}
 
-		bpf_lookup_elem(map_fd, &next_key, values);
+		bpf_map_lookup_elem(map_fd, &next_key, values);
 
 		sum = 0;
 		for (i = 0; i < nr_cpus; i++)
diff --git a/samples/bpf/offwaketime_user.c b/samples/bpf/offwaketime_user.c
index 6f002a9c24fa..9cce2a66bd66 100644
--- a/samples/bpf/offwaketime_user.c
+++ b/samples/bpf/offwaketime_user.c
@@ -49,14 +49,14 @@ static void print_stack(struct key_t *key, __u64 count)
 	int i;
 
 	printf("%s;", key->target);
-	if (bpf_lookup_elem(map_fd[3], &key->tret, ip) != 0) {
+	if (bpf_map_lookup_elem(map_fd[3], &key->tret, ip) != 0) {
 		printf("---;");
 	} else {
 		for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--)
 			print_ksym(ip[i]);
 	}
 	printf("-;");
-	if (bpf_lookup_elem(map_fd[3], &key->wret, ip) != 0) {
+	if (bpf_map_lookup_elem(map_fd[3], &key->wret, ip) != 0) {
 		printf("---;");
 	} else {
 		for (i = 0; i < PERF_MAX_STACK_DEPTH; i++)
@@ -77,8 +77,8 @@ static void print_stacks(int fd)
 	struct key_t key = {}, next_key;
 	__u64 value;
 
-	while (bpf_get_next_key(fd, &key, &next_key) == 0) {
-		bpf_lookup_elem(fd, &next_key, &value);
+	while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
+		bpf_map_lookup_elem(fd, &next_key, &value);
 		print_stack(&next_key, value);
 		key = next_key;
 	}
diff --git a/samples/bpf/sampleip_user.c b/samples/bpf/sampleip_user.c
index 260a6bdd6413..5ac5adf75931 100644
--- a/samples/bpf/sampleip_user.c
+++ b/samples/bpf/sampleip_user.c
@@ -95,8 +95,8 @@ static void print_ip_map(int fd)
 
 	/* fetch IPs and counts */
 	key = 0, i = 0;
-	while (bpf_get_next_key(fd, &key, &next_key) == 0) {
-		bpf_lookup_elem(fd, &next_key, &value);
+	while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
+		bpf_map_lookup_elem(fd, &next_key, &value);
 		counts[i].ip = next_key;
 		counts[i++].count = value;
 		key = next_key;
diff --git a/samples/bpf/sock_example.c b/samples/bpf/sock_example.c
index 28b60baa9fa8..d6b91e9a38ad 100644
--- a/samples/bpf/sock_example.c
+++ b/samples/bpf/sock_example.c
@@ -28,6 +28,8 @@
 #include <stddef.h>
 #include "libbpf.h"
 
+char bpf_log_buf[BPF_LOG_BUF_SIZE];
+
 static int test_sock(void)
 {
 	int sock = -1, map_fd, prog_fd, i, key;
@@ -55,8 +57,8 @@ static int test_sock(void)
 		BPF_EXIT_INSN(),
 	};
 
-	prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog),
-				"GPL", 0);
+	prog_fd = bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog),
+				   "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE);
 	if (prog_fd < 0) {
 		printf("failed to load prog '%s'\n", strerror(errno));
 		goto cleanup;
@@ -72,13 +74,13 @@ static int test_sock(void)
 
 	for (i = 0; i < 10; i++) {
 		key = IPPROTO_TCP;
-		assert(bpf_lookup_elem(map_fd, &key, &tcp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &tcp_cnt) == 0);
 
 		key = IPPROTO_UDP;
-		assert(bpf_lookup_elem(map_fd, &key, &udp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &udp_cnt) == 0);
 
 		key = IPPROTO_ICMP;
-		assert(bpf_lookup_elem(map_fd, &key, &icmp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &icmp_cnt) == 0);
 
 		printf("TCP %lld UDP %lld ICMP %lld packets\n",
 		       tcp_cnt, udp_cnt, icmp_cnt);
diff --git a/samples/bpf/sockex1_user.c b/samples/bpf/sockex1_user.c
index 678ce4693551..9454448bf198 100644
--- a/samples/bpf/sockex1_user.c
+++ b/samples/bpf/sockex1_user.c
@@ -32,13 +32,13 @@ int main(int ac, char **argv)
 		int key;
 
 		key = IPPROTO_TCP;
-		assert(bpf_lookup_elem(map_fd[0], &key, &tcp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd[0], &key, &tcp_cnt) == 0);
 
 		key = IPPROTO_UDP;
-		assert(bpf_lookup_elem(map_fd[0], &key, &udp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd[0], &key, &udp_cnt) == 0);
 
 		key = IPPROTO_ICMP;
-		assert(bpf_lookup_elem(map_fd[0], &key, &icmp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd[0], &key, &icmp_cnt) == 0);
 
 		printf("TCP %lld UDP %lld ICMP %lld bytes\n",
 		       tcp_cnt, udp_cnt, icmp_cnt);
diff --git a/samples/bpf/sockex2_user.c b/samples/bpf/sockex2_user.c
index 8a4085c2d117..6a40600d5a83 100644
--- a/samples/bpf/sockex2_user.c
+++ b/samples/bpf/sockex2_user.c
@@ -39,8 +39,8 @@ int main(int ac, char **argv)
 		int key = 0, next_key;
 		struct pair value;
 
-		while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
-			bpf_lookup_elem(map_fd[0], &next_key, &value);
+		while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) {
+			bpf_map_lookup_elem(map_fd[0], &next_key, &value);
 			printf("ip %s bytes %lld packets %lld\n",
 			       inet_ntoa((struct in_addr){htonl(next_key)}),
 			       value.bytes, value.packets);
diff --git a/samples/bpf/sockex3_user.c b/samples/bpf/sockex3_user.c
index 3fcfd8c4b2a3..9099c4255f23 100644
--- a/samples/bpf/sockex3_user.c
+++ b/samples/bpf/sockex3_user.c
@@ -54,8 +54,8 @@ int main(int argc, char **argv)
 
 		sleep(1);
 		printf("IP     src.port -> dst.port               bytes      packets\n");
-		while (bpf_get_next_key(map_fd[2], &key, &next_key) == 0) {
-			bpf_lookup_elem(map_fd[2], &next_key, &value);
+		while (bpf_map_get_next_key(map_fd[2], &key, &next_key) == 0) {
+			bpf_map_lookup_elem(map_fd[2], &next_key, &value);
 			printf("%s.%05d -> %s.%05d %12lld %12lld\n",
 			       inet_ntoa((struct in_addr){htonl(next_key.src)}),
 			       next_key.port16[0],
diff --git a/samples/bpf/spintest_user.c b/samples/bpf/spintest_user.c
index 311ede532230..80676c25fa50 100644
--- a/samples/bpf/spintest_user.c
+++ b/samples/bpf/spintest_user.c
@@ -31,8 +31,8 @@ int main(int ac, char **argv)
 	for (i = 0; i < 5; i++) {
 		key = 0;
 		printf("kprobing funcs:");
-		while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
-			bpf_lookup_elem(map_fd[0], &next_key, &value);
+		while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) {
+			bpf_map_lookup_elem(map_fd[0], &next_key, &value);
 			assert(next_key == value);
 			sym = ksym_search(value);
 			printf(" %s", sym->name);
@@ -41,8 +41,8 @@ int main(int ac, char **argv)
 		if (key)
 			printf("\n");
 		key = 0;
-		while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0)
-			bpf_delete_elem(map_fd[0], &next_key);
+		while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0)
+			bpf_map_delete_elem(map_fd[0], &next_key);
 		sleep(1);
 	}
 
diff --git a/samples/bpf/tc_l2_redirect_user.c b/samples/bpf/tc_l2_redirect_user.c
index 4013c5337b91..28995a776560 100644
--- a/samples/bpf/tc_l2_redirect_user.c
+++ b/samples/bpf/tc_l2_redirect_user.c
@@ -60,9 +60,9 @@ int main(int argc, char **argv)
 	}
 
 	/* bpf_tunnel_key.remote_ipv4 expects host byte orders */
-	ret = bpf_update_elem(array_fd, &array_key, &ifindex, 0);
+	ret = bpf_map_update_elem(array_fd, &array_key, &ifindex, 0);
 	if (ret) {
-		perror("bpf_update_elem");
+		perror("bpf_map_update_elem");
 		goto out;
 	}
 
diff --git a/samples/bpf/test_cgrp2_array_pin.c b/samples/bpf/test_cgrp2_array_pin.c
index 70e86f7be69d..8a1b8b5d8def 100644
--- a/samples/bpf/test_cgrp2_array_pin.c
+++ b/samples/bpf/test_cgrp2_array_pin.c
@@ -85,9 +85,9 @@ int main(int argc, char **argv)
 		}
 	}
 
-	ret = bpf_update_elem(array_fd, &array_key, &cg2_fd, 0);
+	ret = bpf_map_update_elem(array_fd, &array_key, &cg2_fd, 0);
 	if (ret) {
-		perror("bpf_update_elem");
+		perror("bpf_map_update_elem");
 		goto out;
 	}
 
diff --git a/samples/bpf/test_cgrp2_attach.c b/samples/bpf/test_cgrp2_attach.c
index a19484c45b79..8283ef86d392 100644
--- a/samples/bpf/test_cgrp2_attach.c
+++ b/samples/bpf/test_cgrp2_attach.c
@@ -36,6 +36,8 @@ enum {
 	MAP_KEY_BYTES,
 };
 
+char bpf_log_buf[BPF_LOG_BUF_SIZE];
+
 static int prog_load(int map_fd, int verdict)
 {
 	struct bpf_insn prog[] = {
@@ -67,8 +69,9 @@ static int prog_load(int map_fd, int verdict)
 		BPF_EXIT_INSN(),
 	};
 
-	return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB,
-			     prog, sizeof(prog), "GPL", 0);
+	return bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB,
+				prog, sizeof(prog), "GPL", 0,
+				bpf_log_buf, BPF_LOG_BUF_SIZE);
 }
 
 static int usage(const char *argv0)
@@ -108,10 +111,10 @@ static int attach_filter(int cg_fd, int type, int verdict)
 	}
 	while (1) {
 		key = MAP_KEY_PACKETS;
-		assert(bpf_lookup_elem(map_fd, &key, &pkt_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &pkt_cnt) == 0);
 
 		key = MAP_KEY_BYTES;
-		assert(bpf_lookup_elem(map_fd, &key, &byte_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &byte_cnt) == 0);
 
 		printf("cgroup received %lld packets, %lld bytes\n",
 		       pkt_cnt, byte_cnt);
diff --git a/samples/bpf/test_cgrp2_attach2.c b/samples/bpf/test_cgrp2_attach2.c
index ddfac42ed4df..fc6092fdc3b0 100644
--- a/samples/bpf/test_cgrp2_attach2.c
+++ b/samples/bpf/test_cgrp2_attach2.c
@@ -32,6 +32,8 @@
 #define BAR		"/foo/bar/"
 #define PING_CMD	"ping -c1 -w1 127.0.0.1"
 
+char bpf_log_buf[BPF_LOG_BUF_SIZE];
+
 static int prog_load(int verdict)
 {
 	int ret;
@@ -40,8 +42,9 @@ static int prog_load(int verdict)
 		BPF_EXIT_INSN(),
 	};
 
-	ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB,
-			     prog, sizeof(prog), "GPL", 0);
+	ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB,
+			       prog, sizeof(prog), "GPL", 0,
+			       bpf_log_buf, BPF_LOG_BUF_SIZE);
 
 	if (ret < 0) {
 		log_err("Loading program");
diff --git a/samples/bpf/test_cgrp2_sock.c b/samples/bpf/test_cgrp2_sock.c
index d467b3c1c55c..43b4bde5d05c 100644
--- a/samples/bpf/test_cgrp2_sock.c
+++ b/samples/bpf/test_cgrp2_sock.c
@@ -23,6 +23,8 @@
 
 #include "libbpf.h"
 
+char bpf_log_buf[BPF_LOG_BUF_SIZE];
+
 static int prog_load(int idx)
 {
 	struct bpf_insn prog[] = {
@@ -34,8 +36,8 @@ static int prog_load(int idx)
 		BPF_EXIT_INSN(),
 	};
 
-	return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK, prog, sizeof(prog),
-			     "GPL", 0);
+	return bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, sizeof(prog),
+				"GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE);
 }
 
 static int usage(const char *argv0)
diff --git a/samples/bpf/test_current_task_under_cgroup_user.c b/samples/bpf/test_current_task_under_cgroup_user.c
index 95aaaa846130..65b5fb51c1db 100644
--- a/samples/bpf/test_current_task_under_cgroup_user.c
+++ b/samples/bpf/test_current_task_under_cgroup_user.c
@@ -36,7 +36,7 @@ int main(int argc, char **argv)
 	if (!cg2)
 		goto err;
 
-	if (bpf_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) {
+	if (bpf_map_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) {
 		log_err("Adding target cgroup to map");
 		goto err;
 	}
@@ -50,7 +50,7 @@ int main(int argc, char **argv)
 	 */
 
 	sync();
-	bpf_lookup_elem(map_fd[1], &idx, &remote_pid);
+	bpf_map_lookup_elem(map_fd[1], &idx, &remote_pid);
 
 	if (local_pid != remote_pid) {
 		fprintf(stderr,
@@ -64,10 +64,10 @@ int main(int argc, char **argv)
 		goto err;
 
 	remote_pid = 0;
-	bpf_update_elem(map_fd[1], &idx, &remote_pid, BPF_ANY);
+	bpf_map_update_elem(map_fd[1], &idx, &remote_pid, BPF_ANY);
 
 	sync();
-	bpf_lookup_elem(map_fd[1], &idx, &remote_pid);
+	bpf_map_lookup_elem(map_fd[1], &idx, &remote_pid);
 
 	if (local_pid == remote_pid) {
 		fprintf(stderr, "BPF cgroup negative test did not work\n");
diff --git a/samples/bpf/test_lru_dist.c b/samples/bpf/test_lru_dist.c
index 316230a0ed23..d96dc88d3b04 100644
--- a/samples/bpf/test_lru_dist.c
+++ b/samples/bpf/test_lru_dist.c
@@ -134,7 +134,7 @@ static int pfect_lru_lookup_or_insert(struct pfect_lru *lru,
 	int seen = 0;
 
 	lru->total++;
-	if (!bpf_lookup_elem(lru->map_fd, &key, &node)) {
+	if (!bpf_map_lookup_elem(lru->map_fd, &key, &node)) {
 		if (node) {
 			list_move(&node->list, &lru->list);
 			return 1;
@@ -151,7 +151,7 @@ static int pfect_lru_lookup_or_insert(struct pfect_lru *lru,
 		node = list_last_entry(&lru->list,
 				       struct pfect_lru_node,
 				       list);
-		bpf_update_elem(lru->map_fd, &node->key, &null_node, BPF_EXIST);
+		bpf_map_update_elem(lru->map_fd, &node->key, &null_node, BPF_EXIST);
 	}
 
 	node->key = key;
@@ -159,10 +159,10 @@ static int pfect_lru_lookup_or_insert(struct pfect_lru *lru,
 
 	lru->nr_misses++;
 	if (seen) {
-		assert(!bpf_update_elem(lru->map_fd, &key, &node, BPF_EXIST));
+		assert(!bpf_map_update_elem(lru->map_fd, &key, &node, BPF_EXIST));
 	} else {
 		lru->nr_unique++;
-		assert(!bpf_update_elem(lru->map_fd, &key, &node, BPF_NOEXIST));
+		assert(!bpf_map_update_elem(lru->map_fd, &key, &node, BPF_NOEXIST));
 	}
 
 	return seen;
@@ -285,11 +285,11 @@ static void do_test_lru_dist(int task, void *data)
 
 		pfect_lru_lookup_or_insert(&pfect_lru, key);
 
-		if (!bpf_lookup_elem(lru_map_fd, &key, &value))
+		if (!bpf_map_lookup_elem(lru_map_fd, &key, &value))
 			continue;
 
-		if (bpf_update_elem(lru_map_fd, &key, &value, BPF_NOEXIST)) {
-			printf("bpf_update_elem(lru_map_fd, %llu): errno:%d\n",
+		if (bpf_map_update_elem(lru_map_fd, &key, &value, BPF_NOEXIST)) {
+			printf("bpf_map_update_elem(lru_map_fd, %llu): errno:%d\n",
 			       key, errno);
 			assert(0);
 		}
@@ -358,19 +358,19 @@ static void test_lru_loss0(int map_type, int map_flags)
 	for (key = 1; key <= 1000; key++) {
 		int start_key, end_key;
 
-		assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0);
+		assert(bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0);
 
 		start_key = 101;
 		end_key = min(key, 900);
 
 		while (start_key <= end_key) {
-			bpf_lookup_elem(map_fd, &start_key, value);
+			bpf_map_lookup_elem(map_fd, &start_key, value);
 			start_key++;
 		}
 	}
 
 	for (key = 1; key <= 1000; key++) {
-		if (bpf_lookup_elem(map_fd, &key, value)) {
+		if (bpf_map_lookup_elem(map_fd, &key, value)) {
 			if (key <= 100)
 				old_unused_losses++;
 			else if (key <= 900)
@@ -408,10 +408,10 @@ static void test_lru_loss1(int map_type, int map_flags)
 	value[0] = 1234;
 
 	for (key = 1; key <= 1000; key++)
-		assert(!bpf_update_elem(map_fd, &key, value, BPF_NOEXIST));
+		assert(!bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST));
 
 	for (key = 1; key <= 1000; key++) {
-		if (bpf_lookup_elem(map_fd, &key, value))
+		if (bpf_map_lookup_elem(map_fd, &key, value))
 			nr_losses++;
 	}
 
@@ -436,7 +436,7 @@ static void do_test_parallel_lru_loss(int task, void *data)
 	next_ins_key = stable_base;
 	value[0] = 1234;
 	for (i = 0; i < nr_stable_elems; i++) {
-		assert(bpf_update_elem(map_fd, &next_ins_key, value,
+		assert(bpf_map_update_elem(map_fd, &next_ins_key, value,
 				       BPF_NOEXIST) == 0);
 		next_ins_key++;
 	}
@@ -448,9 +448,9 @@ static void do_test_parallel_lru_loss(int task, void *data)
 
 		if (rn % 10) {
 			key = rn % nr_stable_elems + stable_base;
-			bpf_lookup_elem(map_fd, &key, value);
+			bpf_map_lookup_elem(map_fd, &key, value);
 		} else {
-			bpf_update_elem(map_fd, &next_ins_key, value,
+			bpf_map_update_elem(map_fd, &next_ins_key, value,
 					BPF_NOEXIST);
 			next_ins_key++;
 		}
@@ -458,7 +458,7 @@ static void do_test_parallel_lru_loss(int task, void *data)
 
 	key = stable_base;
 	for (i = 0; i < nr_stable_elems; i++) {
-		if (bpf_lookup_elem(map_fd, &key, value))
+		if (bpf_map_lookup_elem(map_fd, &key, value))
 			nr_losses++;
 		key++;
 	}
diff --git a/samples/bpf/test_probe_write_user_user.c b/samples/bpf/test_probe_write_user_user.c
index a44bf347bedd..b5bf178a6ecc 100644
--- a/samples/bpf/test_probe_write_user_user.c
+++ b/samples/bpf/test_probe_write_user_user.c
@@ -50,7 +50,7 @@ int main(int ac, char **argv)
 	mapped_addr_in->sin_port = htons(5555);
 	mapped_addr_in->sin_addr.s_addr = inet_addr("255.255.255.255");
 
-	assert(!bpf_update_elem(map_fd[0], &mapped_addr, &serv_addr, BPF_ANY));
+	assert(!bpf_map_update_elem(map_fd[0], &mapped_addr, &serv_addr, BPF_ANY));
 
 	assert(listen(serverfd, 5) == 0);
 
diff --git a/samples/bpf/trace_event_user.c b/samples/bpf/trace_event_user.c
index 9a130d31ecf2..704fe9fa77b2 100644
--- a/samples/bpf/trace_event_user.c
+++ b/samples/bpf/trace_event_user.c
@@ -61,14 +61,14 @@ static void print_stack(struct key_t *key, __u64 count)
 	int i;
 
 	printf("%3lld %s;", count, key->comm);
-	if (bpf_lookup_elem(map_fd[1], &key->kernstack, ip) != 0) {
+	if (bpf_map_lookup_elem(map_fd[1], &key->kernstack, ip) != 0) {
 		printf("---;");
 	} else {
 		for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--)
 			print_ksym(ip[i]);
 	}
 	printf("-;");
-	if (bpf_lookup_elem(map_fd[1], &key->userstack, ip) != 0) {
+	if (bpf_map_lookup_elem(map_fd[1], &key->userstack, ip) != 0) {
 		printf("---;");
 	} else {
 		for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--)
@@ -98,10 +98,10 @@ static void print_stacks(void)
 	int fd = map_fd[0], stack_map = map_fd[1];
 
 	sys_read_seen = sys_write_seen = false;
-	while (bpf_get_next_key(fd, &key, &next_key) == 0) {
-		bpf_lookup_elem(fd, &next_key, &value);
+	while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
+		bpf_map_lookup_elem(fd, &next_key, &value);
 		print_stack(&next_key, value);
-		bpf_delete_elem(fd, &next_key);
+		bpf_map_delete_elem(fd, &next_key);
 		key = next_key;
 	}
 
@@ -111,8 +111,8 @@ static void print_stacks(void)
 	}
 
 	/* clear stack map */
-	while (bpf_get_next_key(stack_map, &stackid, &next_id) == 0) {
-		bpf_delete_elem(stack_map, &next_id);
+	while (bpf_map_get_next_key(stack_map, &stackid, &next_id) == 0) {
+		bpf_map_delete_elem(stack_map, &next_id);
 		stackid = next_id;
 	}
 }
diff --git a/samples/bpf/trace_output_user.c b/samples/bpf/trace_output_user.c
index 661a7d052f2c..3bedd945def1 100644
--- a/samples/bpf/trace_output_user.c
+++ b/samples/bpf/trace_output_user.c
@@ -162,7 +162,7 @@ static void test_bpf_perf_event(void)
 	pmu_fd = perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
 
 	assert(pmu_fd >= 0);
-	assert(bpf_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0);
+	assert(bpf_map_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0);
 	ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
 }
 
diff --git a/samples/bpf/tracex2_user.c b/samples/bpf/tracex2_user.c
index 3e225e331f66..ded9804c5034 100644
--- a/samples/bpf/tracex2_user.c
+++ b/samples/bpf/tracex2_user.c
@@ -48,12 +48,12 @@ static void print_hist_for_pid(int fd, void *task)
 	long max_value = 0;
 	int i, ind;
 
-	while (bpf_get_next_key(fd, &key, &next_key) == 0) {
+	while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
 		if (memcmp(&next_key, task, SIZE)) {
 			key = next_key;
 			continue;
 		}
-		bpf_lookup_elem(fd, &next_key, values);
+		bpf_map_lookup_elem(fd, &next_key, values);
 		value = 0;
 		for (i = 0; i < nr_cpus; i++)
 			value += values[i];
@@ -83,7 +83,7 @@ static void print_hist(int fd)
 	int task_cnt = 0;
 	int i;
 
-	while (bpf_get_next_key(fd, &key, &next_key) == 0) {
+	while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
 		int found = 0;
 
 		for (i = 0; i < task_cnt; i++)
@@ -136,8 +136,8 @@ int main(int ac, char **argv)
 
 	for (i = 0; i < 5; i++) {
 		key = 0;
-		while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
-			bpf_lookup_elem(map_fd[0], &next_key, &value);
+		while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) {
+			bpf_map_lookup_elem(map_fd[0], &next_key, &value);
 			printf("location 0x%lx count %ld\n", next_key, value);
 			key = next_key;
 		}
diff --git a/samples/bpf/tracex3_user.c b/samples/bpf/tracex3_user.c
index d0851cb4fa8d..8f7d199d5945 100644
--- a/samples/bpf/tracex3_user.c
+++ b/samples/bpf/tracex3_user.c
@@ -28,7 +28,7 @@ static void clear_stats(int fd)
 
 	memset(values, 0, sizeof(values));
 	for (key = 0; key < SLOTS; key++)
-		bpf_update_elem(fd, &key, values, BPF_ANY);
+		bpf_map_update_elem(fd, &key, values, BPF_ANY);
 }
 
 const char *color[] = {
@@ -89,7 +89,7 @@ static void print_hist(int fd)
 	int i;
 
 	for (key = 0; key < SLOTS; key++) {
-		bpf_lookup_elem(fd, &key, values);
+		bpf_map_lookup_elem(fd, &key, values);
 		value = 0;
 		for (i = 0; i < nr_cpus; i++)
 			value += values[i];
diff --git a/samples/bpf/tracex4_user.c b/samples/bpf/tracex4_user.c
index bc4a3bdea6ed..03449f773cb1 100644
--- a/samples/bpf/tracex4_user.c
+++ b/samples/bpf/tracex4_user.c
@@ -37,8 +37,8 @@ static void print_old_objects(int fd)
 	key = write(1, "\e[1;1H\e[2J", 12); /* clear screen */
 
 	key = -1;
-	while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
-		bpf_lookup_elem(map_fd[0], &next_key, &v);
+	while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) {
+		bpf_map_lookup_elem(map_fd[0], &next_key, &v);
 		key = next_key;
 		if (val - v.val < 1000000000ll)
 			/* object was allocated more then 1 sec ago */
diff --git a/samples/bpf/tracex6_user.c b/samples/bpf/tracex6_user.c
index 8ea4976cfcf1..179297cb4d35 100644
--- a/samples/bpf/tracex6_user.c
+++ b/samples/bpf/tracex6_user.c
@@ -36,7 +36,7 @@ static void test_bpf_perf_event(void)
 			goto exit;
 		}
 
-		bpf_update_elem(map_fd[0], &i, &pmu_fd[i], BPF_ANY);
+		bpf_map_update_elem(map_fd[0], &i, &pmu_fd[i], BPF_ANY);
 		ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0);
 	}
 
diff --git a/samples/bpf/xdp1_user.c b/samples/bpf/xdp1_user.c
index 5f040a0d7712..d2be65d1fd86 100644
--- a/samples/bpf/xdp1_user.c
+++ b/samples/bpf/xdp1_user.c
@@ -43,7 +43,7 @@ static void poll_stats(int interval)
 		for (key = 0; key < nr_keys; key++) {
 			__u64 sum = 0;
 
-			assert(bpf_lookup_elem(map_fd[0], &key, values) == 0);
+			assert(bpf_map_lookup_elem(map_fd[0], &key, values) == 0);
 			for (i = 0; i < nr_cpus; i++)
 				sum += (values[i] - prev[key][i]);
 			if (sum)
diff --git a/samples/bpf/xdp_tx_iptunnel_user.c b/samples/bpf/xdp_tx_iptunnel_user.c
index 7a71f5c74684..70e192fc61aa 100644
--- a/samples/bpf/xdp_tx_iptunnel_user.c
+++ b/samples/bpf/xdp_tx_iptunnel_user.c
@@ -51,7 +51,7 @@ static void poll_stats(unsigned int kill_after_s)
 		for (proto = 0; proto < nr_protos; proto++) {
 			__u64 sum = 0;
 
-			assert(bpf_lookup_elem(map_fd[0], &proto, values) == 0);
+			assert(bpf_map_lookup_elem(map_fd[0], &proto, values) == 0);
 			for (i = 0; i < nr_cpus; i++)
 				sum += (values[i] - prev[proto][i]);
 
@@ -237,8 +237,8 @@ int main(int argc, char **argv)
 
 	while (min_port <= max_port) {
 		vip.dport = htons(min_port++);
-		if (bpf_update_elem(map_fd[1], &vip, &tnl, BPF_NOEXIST)) {
-			perror("bpf_update_elem(&vip2tnl)");
+		if (bpf_map_update_elem(map_fd[1], &vip, &tnl, BPF_NOEXIST)) {
+			perror("bpf_map_update_elem(&vip2tnl)");
 			return 1;
 		}
 	}
-- 
2.10.2

^ permalink raw reply related

* [PATCHv5 perf/core 4/5] samples/bpf: Remove perf_event_open() declaration
From: Joe Stringer @ 2016-12-16 18:32 UTC (permalink / raw)
  To: acme; +Cc: linux-kernel, netdev, wangnan0, ast, daniel
In-Reply-To: <20161216183259.14840-1-joe@ovn.org>

This declaration was made in samples/bpf/libbpf.c for convenience, but
there's already one in tools/perf/perf-sys.h. Reuse that one.

Committer notes:

Testing it:

  $ make -j4 O=../build/v4.9.0-rc8+ samples/bpf/
  make[1]: Entering directory '/home/build/v4.9.0-rc8+'
    CHK     include/config/kernel.release
    GEN     ./Makefile
    CHK     include/generated/uapi/linux/version.h
    Using /home/acme/git/linux as source for kernel
    CHK     include/generated/utsrelease.h
    CHK     include/generated/timeconst.h
    CHK     include/generated/bounds.h
    CHK     include/generated/asm-offsets.h
    CALL    /home/acme/git/linux/scripts/checksyscalls.sh
    HOSTCC  samples/bpf/test_verifier.o
    HOSTCC  samples/bpf/libbpf.o
    HOSTCC  samples/bpf/../../tools/lib/bpf/bpf.o
    HOSTCC  samples/bpf/test_maps.o
    HOSTCC  samples/bpf/sock_example.o
    HOSTCC  samples/bpf/bpf_load.o
<SNIP>
    HOSTLD  samples/bpf/trace_event
    HOSTLD  samples/bpf/sampleip
    HOSTLD  samples/bpf/tc_l2_redirect
  make[1]: Leaving directory '/home/build/v4.9.0-rc8+'
  $

Signed-off-by: Joe Stringer <joe@ovn.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/20161209024620.31660-7-joe@ovn.org
[ Use -I$(srctree)/tools/lib/ to support out of source code tree builds ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
v5: No change.
---
 samples/bpf/Makefile            | 2 ++
 samples/bpf/bpf_load.c          | 3 ++-
 samples/bpf/libbpf.c            | 7 -------
 samples/bpf/libbpf.h            | 3 ---
 samples/bpf/sampleip_user.c     | 3 ++-
 samples/bpf/trace_event_user.c  | 9 +++++----
 samples/bpf/trace_output_user.c | 3 ++-
 samples/bpf/tracex6_user.c      | 3 ++-
 8 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 81b0ef2f7994..5a73f5a7ace1 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -109,6 +109,8 @@ always += xdp_tx_iptunnel_kern.o
 HOSTCFLAGS += -I$(objtree)/usr/include
 HOSTCFLAGS += -I$(srctree)/tools/lib/
 HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/
+HOSTCFLAGS += -I$(srctree)/tools/lib/ -I$(srctree)/tools/include
+HOSTCFLAGS += -I$(srctree)/tools/perf
 
 HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable
 HOSTLOADLIBES_fds_example += -lelf
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 1bfb43394013..396e204888b3 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -23,6 +23,7 @@
 #include <ctype.h>
 #include "libbpf.h"
 #include "bpf_load.h"
+#include "perf-sys.h"
 
 #define DEBUGFS "/sys/kernel/debug/tracing/"
 
@@ -179,7 +180,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 	id = atoi(buf);
 	attr.config = id;
 
-	efd = perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
+	efd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
 	if (efd < 0) {
 		printf("event %d fd %d err %s\n", id, efd, strerror(errno));
 		return -1;
diff --git a/samples/bpf/libbpf.c b/samples/bpf/libbpf.c
index d9af876b4a2c..bee473a494f1 100644
--- a/samples/bpf/libbpf.c
+++ b/samples/bpf/libbpf.c
@@ -34,10 +34,3 @@ int open_raw_sock(const char *name)
 
 	return sock;
 }
-
-int perf_event_open(struct perf_event_attr *attr, int pid, int cpu,
-		    int group_fd, unsigned long flags)
-{
-	return syscall(__NR_perf_event_open, attr, pid, cpu,
-		       group_fd, flags);
-}
diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h
index cc815624aacf..09aedc320009 100644
--- a/samples/bpf/libbpf.h
+++ b/samples/bpf/libbpf.h
@@ -188,7 +188,4 @@ struct bpf_insn;
 /* create RAW socket and bind to interface 'name' */
 int open_raw_sock(const char *name);
 
-struct perf_event_attr;
-int perf_event_open(struct perf_event_attr *attr, int pid, int cpu,
-		    int group_fd, unsigned long flags);
 #endif
diff --git a/samples/bpf/sampleip_user.c b/samples/bpf/sampleip_user.c
index 5ac5adf75931..be59d7dcbdde 100644
--- a/samples/bpf/sampleip_user.c
+++ b/samples/bpf/sampleip_user.c
@@ -21,6 +21,7 @@
 #include <sys/ioctl.h>
 #include "libbpf.h"
 #include "bpf_load.h"
+#include "perf-sys.h"
 
 #define DEFAULT_FREQ	99
 #define DEFAULT_SECS	5
@@ -49,7 +50,7 @@ static int sampling_start(int *pmu_fd, int freq)
 	};
 
 	for (i = 0; i < nr_cpus; i++) {
-		pmu_fd[i] = perf_event_open(&pe_sample_attr, -1 /* pid */, i,
+		pmu_fd[i] = sys_perf_event_open(&pe_sample_attr, -1 /* pid */, i,
 					    -1 /* group_fd */, 0 /* flags */);
 		if (pmu_fd[i] < 0) {
 			fprintf(stderr, "ERROR: Initializing perf sampling\n");
diff --git a/samples/bpf/trace_event_user.c b/samples/bpf/trace_event_user.c
index 704fe9fa77b2..0c5561d193a4 100644
--- a/samples/bpf/trace_event_user.c
+++ b/samples/bpf/trace_event_user.c
@@ -20,6 +20,7 @@
 #include <sys/resource.h>
 #include "libbpf.h"
 #include "bpf_load.h"
+#include "perf-sys.h"
 
 #define SAMPLE_FREQ 50
 
@@ -125,9 +126,9 @@ static void test_perf_event_all_cpu(struct perf_event_attr *attr)
 
 	/* open perf_event on all cpus */
 	for (i = 0; i < nr_cpus; i++) {
-		pmu_fd[i] = perf_event_open(attr, -1, i, -1, 0);
+		pmu_fd[i] = sys_perf_event_open(attr, -1, i, -1, 0);
 		if (pmu_fd[i] < 0) {
-			printf("perf_event_open failed\n");
+			printf("sys_perf_event_open failed\n");
 			goto all_cpu_err;
 		}
 		assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0);
@@ -146,9 +147,9 @@ static void test_perf_event_task(struct perf_event_attr *attr)
 	int pmu_fd;
 
 	/* open task bound event */
-	pmu_fd = perf_event_open(attr, 0, -1, -1, 0);
+	pmu_fd = sys_perf_event_open(attr, 0, -1, -1, 0);
 	if (pmu_fd < 0) {
-		printf("perf_event_open failed\n");
+		printf("sys_perf_event_open failed\n");
 		return;
 	}
 	assert(ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0);
diff --git a/samples/bpf/trace_output_user.c b/samples/bpf/trace_output_user.c
index 3bedd945def1..7449fac2819e 100644
--- a/samples/bpf/trace_output_user.c
+++ b/samples/bpf/trace_output_user.c
@@ -21,6 +21,7 @@
 #include <signal.h>
 #include "libbpf.h"
 #include "bpf_load.h"
+#include "perf-sys.h"
 
 static int pmu_fd;
 
@@ -159,7 +160,7 @@ static void test_bpf_perf_event(void)
 	};
 	int key = 0;
 
-	pmu_fd = perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
+	pmu_fd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
 
 	assert(pmu_fd >= 0);
 	assert(bpf_map_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0);
diff --git a/samples/bpf/tracex6_user.c b/samples/bpf/tracex6_user.c
index 179297cb4d35..ca7874ed77f4 100644
--- a/samples/bpf/tracex6_user.c
+++ b/samples/bpf/tracex6_user.c
@@ -10,6 +10,7 @@
 #include <linux/bpf.h>
 #include "libbpf.h"
 #include "bpf_load.h"
+#include "perf-sys.h"
 
 #define SAMPLE_PERIOD  0x7fffffffffffffffULL
 
@@ -30,7 +31,7 @@ static void test_bpf_perf_event(void)
 	};
 
 	for (i = 0; i < nr_cpus; i++) {
-		pmu_fd[i] = perf_event_open(&attr_insn_pmu, -1/*pid*/, i/*cpu*/, -1/*group_fd*/, 0);
+		pmu_fd[i] = sys_perf_event_open(&attr_insn_pmu, -1/*pid*/, i/*cpu*/, -1/*group_fd*/, 0);
 		if (pmu_fd[i] < 0) {
 			printf("event syscall failed\n");
 			goto exit;
-- 
2.10.2

^ permalink raw reply related

* [PATCHv5 perf/core 0/5] Reuse libbpf from samples/bpf
From: Joe Stringer @ 2016-12-16 18:32 UTC (permalink / raw)
  To: acme; +Cc: linux-kernel, netdev, wangnan0, ast, daniel

Update tools/lib/bpf to provide the remaining bpf wrapper pieces needed by the
samples/bpf/ code, then get rid of all of the duplicate BPF libraries in
samples/bpf/libbpf.[ch].

---
v5: Fixed prog_size vs. instruction count API difference in bpf_load_program()

REBASE: Rebased v3 that was applied to perf/core.
        Resolved merge conflict with net-next.
        New patch shifts bpf_prog_{attach,detach}() to libbpf.
        Drop unnecessary build targets
        Drop extra unneeded log buffers

v3: Add ack for first patch.
    Split out second patch from v2 into separate changes for remaining diff.
    Add patches to switch samples/bpf over to using tools/lib/.

(Was "libbpf: Synchronize implementations")
v2: Don't shift non-bpf code into libbpf.
    Drop the patch to synchronize ELF definitions with tc.

v1: https://www.mail-archive.com/netdev@vger.kernel.org/msg135088.html
    First post.

Joe Stringer (5):
  samples/bpf: Make samples more libbpf-centric
  samples/bpf: Switch over to libbpf
  tools lib bpf: Add bpf_prog_{attach,detach}
  samples/bpf: Remove perf_event_open() declaration
  samples/bpf: Move open_raw_sock to separate header

 samples/bpf/Makefile                              |  70 +++++----
 samples/bpf/README.rst                            |   4 +-
 samples/bpf/bpf_load.c                            |  21 ++-
 samples/bpf/bpf_load.h                            |   3 +
 samples/bpf/fds_example.c                         |  11 +-
 samples/bpf/lathist_user.c                        |   2 +-
 samples/bpf/libbpf.c                              | 176 ----------------------
 samples/bpf/libbpf.h                              |  28 +---
 samples/bpf/lwt_len_hist_user.c                   |   6 +-
 samples/bpf/offwaketime_user.c                    |   8 +-
 samples/bpf/sampleip_user.c                       |   7 +-
 samples/bpf/sock_example.c                        |  14 +-
 samples/bpf/sock_example.h                        |  35 +++++
 samples/bpf/sockex1_user.c                        |   7 +-
 samples/bpf/sockex2_user.c                        |   5 +-
 samples/bpf/sockex3_user.c                        |   5 +-
 samples/bpf/spintest_user.c                       |   8 +-
 samples/bpf/tc_l2_redirect_user.c                 |   4 +-
 samples/bpf/test_cgrp2_array_pin.c                |   4 +-
 samples/bpf/test_cgrp2_attach.c                   |  12 +-
 samples/bpf/test_cgrp2_attach2.c                  |   8 +-
 samples/bpf/test_cgrp2_sock.c                     |   7 +-
 samples/bpf/test_current_task_under_cgroup_user.c |   8 +-
 samples/bpf/test_lru_dist.c                       |  32 ++--
 samples/bpf/test_probe_write_user_user.c          |   2 +-
 samples/bpf/trace_event_user.c                    |  23 +--
 samples/bpf/trace_output_user.c                   |   5 +-
 samples/bpf/tracex2_user.c                        |  10 +-
 samples/bpf/tracex3_user.c                        |   4 +-
 samples/bpf/tracex4_user.c                        |   4 +-
 samples/bpf/tracex6_user.c                        |   5 +-
 samples/bpf/xdp1_user.c                           |   2 +-
 samples/bpf/xdp_tx_iptunnel_user.c                |   6 +-
 tools/lib/bpf/bpf.c                               |  21 +++
 tools/lib/bpf/bpf.h                               |   3 +
 35 files changed, 238 insertions(+), 332 deletions(-)
 delete mode 100644 samples/bpf/libbpf.c
 create mode 100644 samples/bpf/sock_example.h

-- 
2.10.2

^ permalink raw reply

* Re: [PATCH 2/2] encx24j600: Fix some checkstyle warnings
From: David Miller @ 2016-12-16 18:32 UTC (permalink / raw)
  To: jeroen.de_wachter.ext; +Cc: jringle, akpm, netdev
In-Reply-To: <1481549349-8199-2-git-send-email-jeroen.de_wachter.ext@nokia.com>

From: <jeroen.de_wachter.ext@nokia.com>
Date: Mon, 12 Dec 2016 14:29:09 +0100

> From: Jeroen De Wachter <jeroen.de_wachter.ext@nokia.com>
> 
> Signed-off-by: Jeroen De Wachter <jeroen.de_wachter.ext@nokia.com>

Applied.

^ permalink raw reply

* Re: [PATCH 1/2] encx24j600: bugfix - always move ERXTAIL to next packet in encx24j600_rx_packets
From: David Miller @ 2016-12-16 18:32 UTC (permalink / raw)
  To: jeroen.de_wachter.ext; +Cc: jringle, akpm, netdev
In-Reply-To: <1481549349-8199-1-git-send-email-jeroen.de_wachter.ext@nokia.com>

From: <jeroen.de_wachter.ext@nokia.com>
Date: Mon, 12 Dec 2016 14:29:08 +0100

> From: Jeroen De Wachter <jeroen.de_wachter.ext@nokia.com>
> 
> Before, encx24j600_rx_packets did not update encx24j600_priv's next_packet
> member when an error occurred during packet handling (either because the
> packet's RSV header indicates an error or because the encx24j600_receive_packet
> method can't allocate an sk_buff).
> 
> If the next_packet member is not updated, the ERXTAIL register will be set to
> the same value it had before, which means the bad packet remains in the
> component's memory and its RSV header will be read again when a new packet
> arrives. If the RSV header indicates a bad packet or if sk_buff allocation
> continues to fail, new packets will be stored in the component's memory until
> that memory is full, after which packets will be dropped.
> 
> The SETPKTDEC command is always executed though, so the encx24j600 hardware has
> an incorrect count of the packets in its memory.
> 
> To prevent this, the next_packet member should always be updated, allowing the
> packet to be skipped (either because it's bad, as indicated in its RSV header,
> or because allocating an sk_buff failed). In the allocation failure case, this
> does mean dropping a valid packet, but dropping the oldest packet to keep as
> much memory as possible available for new packets seems preferable to keeping
> old (but valid) packets around while dropping new ones.
> 
> Signed-off-by: Jeroen De Wachter <jeroen.de_wachter.ext@nokia.com>

Applied.

^ permalink raw reply

* Re: [PATCH 0/2] net: ethernet: hisilicon: set dev->dev.parent before PHY connect
From: David Miller @ 2016-12-16 18:30 UTC (permalink / raw)
  To: lidongpo
  Cc: yisen.zhuang, salil.mehta, f.fainelli, xuejiancheng,
	benjamin.chenhao, caizhiyong, netdev, linux-kernel
In-Reply-To: <1481544223-207906-1-git-send-email-lidongpo@hisilicon.com>

From: Dongpo Li <lidongpo@hisilicon.com>
Date: Mon, 12 Dec 2016 20:03:41 +0800

> This patch series builds atop:
> ec988ad78ed6d184a7f4ca6b8e962b0e8f1de461 ("phy: Don't increment MDIO bus
> refcount unless it's a different owner")
> 
> I have checked all the hisilicon ethernet driver and found only two drivers
> need to be fixed to make sure set dev->dev.parent before PHY connect.

Series applied, thanks.

^ permalink raw reply

* [patch net] mlxsw: spectrum: Mark split ports as such
From: Jiri Pirko @ 2016-12-16 18:29 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, eladr, yotamg, nogahf, arkadis, tamirw

From: Ido Schimmel <idosch@mellanox.com>

When a port is split we should mark it as such, as otherwise the split
ports aren't renamed correctly (e.g. sw1p3 -> sw1p3s1) and the unsplit
operation fails:

$ devlink port split sw1p3 count 4
$ devlink port unsplit eth0
devlink answers: Invalid argument
[  598.565307] mlxsw_spectrum 0000:03:00.0 eth0: Port wasn't split

Fixes: 67963a33b4fd ("mlxsw: Make devlink port instances independent of spectrum/switchx2 port instances")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reported-by: Tamir Winetroub <tamirw@mellanox.com>
Reviewed-by: Elad Raz <eladr@mellanox.com>
Tested-by: Tamir Winetroub <tamirw@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index fece974..d768c7b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2404,7 +2404,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 			local_port);
 		return err;
 	}
-	err = __mlxsw_sp_port_create(mlxsw_sp, local_port, false,
+	err = __mlxsw_sp_port_create(mlxsw_sp, local_port, split,
 				     module, width, lane);
 	if (err)
 		goto err_port_create;
-- 
2.7.4

^ permalink raw reply related

* RE: [PATCH RFC] liquidio: make timeout HZ independent
From: Chickles, Derek @ 2016-12-16 17:53 UTC (permalink / raw)
  To: Nicholas Mc Guire
  Cc: Burla, Satananda, Manlunas, Felix, Vatsavayi, Raghu,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <1481871440-24859-1-git-send-email-hofrat@osadl.org>

> -----Original Message-----
> From: Nicholas Mc Guire [mailto:hofrat@osadl.org]
> Sent: Thursday, December 15, 2016 10:57 PM
> To: Chickles, Derek
> Cc: Burla, Satananda; Manlunas, Felix; Vatsavayi, Raghu;
> netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Nicholas Mc Guire
> Subject: [PATCH RFC] liquidio: make timeout HZ independent
> 
> schedule_timeout_* takes a timeout in jiffies but the code currently is
> passing in a constant which makes this timeout HZ dependent, so pass it
> through msecs_to_jiffies() to fix this up.
> 
> Fixes: commit b0d66369edcd ("liquidio VF error handling")
> Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org>
> ---
> 
> Problem found by coccinelle spatch
> 
> The current wait time can vary by a factor 10 depending on the HZ
> setting chose, which does not seem reasonable here.
> 
> The below patch sets the timeout to 100ms - it is though not clear
> if this is the intent or if it should be longer/shorter as it is not
> clear what HZ setting was assumed during design and used for testing.
> 
> This needs an ack by someone who knows the device and can confirm that
> 100ms is reasonable to wait for completion of in-flight requests.

Yes, 100ms was the intent here.

Thanks for catching this.

Derek

^ permalink raw reply

* Re: [PATCH net] net: dsa: mv88e6xxx: Fix opps when adding vlan bridge
From: David Miller @ 2016-12-16 18:27 UTC (permalink / raw)
  To: andrew; +Cc: netdev, vivien.didelot
In-Reply-To: <1481486839-19502-1-git-send-email-andrew@lunn.ch>

From: Andrew Lunn <andrew@lunn.ch>
Date: Sun, 11 Dec 2016 21:07:19 +0100

> A port is not necessarily assigned to a netdev. And a port does not
> need to be a member of a bridge. So when iterating over all ports,
> check before using the netdev and bridge_dev for a port. Otherwise we
> dereference a NULL pointer.
> 
> Fixes: da9c359e19f0 ("net: dsa: mv88e6xxx: check hardware VLAN in use")
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Applied.

^ permalink raw reply

* Re: net/3com/3c515: Fix timer handling, prevent leaks and crashes
From: David Miller @ 2016-12-16 18:25 UTC (permalink / raw)
  To: tglx; +Cc: linux-kernel, netdev, tedheadster, luto
In-Reply-To: <alpine.DEB.2.20.1612111826310.18281@nanos>

From: Thomas Gleixner <tglx@linutronix.de>
Date: Sun, 11 Dec 2016 18:31:22 +0100 (CET)

> The timer handling in this driver is broken in several ways:
> 
> - corkscrew_open() initializes and arms a timer before requesting the
>   device interrupt. If the request fails the timer stays armed.
> 
>   A second call to corkscrew_open will unconditionally reinitialize the
>   quued timer and arm it again. Also a immediate device removal will leave
>   the timer queued because close() is not called (open() failed) and
>   therefore nothing issues del_timer().
> 
>   The reinitialization corrupts the link chain in the timer wheel hash
>   bucket and causes a NULL pointer dereference when the timer wheel tries
>   to operate on that hash bucket. Immediate device removal lets the link
>   chain poke into freed and possibly reused memory.
> 
>   Solution: Arm the timer after the successful irq request.
> 
> - corkscrew_close() uses del_timer()
> 
>   On close the timer is disarmed with del_timer() which lets the following
>   code race against a concurrent timer expiry function.
> 
>   Solution: Use del_timer_sync() instead
> 
> - corkscrew_close() calls del_timer() unconditionally
> 
>   del_timer() is invoked even if the timer was never initialized. This
>   works by chance because the struct containing the timer is zeroed at
>   allocation time.
> 
>   Solution: Move the setup of the timer into corkscrew_setup().
> 
> Reported-by: Matthew Whitehead <tedheadster@gmail.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Applied, thanks Thomas.

^ permalink raw reply

* [PATCH 1/1] tools: net: bpf_dbg.c fixed keyboard typo
From: Ozgur Karatas @ 2016-12-16 18:21 UTC (permalink / raw)
  To: David Miller; +Cc: linux-kernel, netdev


This patch fixed to keyboard typo, brackets not closed. 
I think, it should be close to parenthes.

Signed-off-by: Ozgur Karatas <okaratas@member.fsf.org>
---
 tools/net/bpf_dbg.c       | 2 +-
 1 files changed, 1 insertion(+), 1 deletions(-)

diff --git a/tools/net/bpf_dbg.c b/tools/net/bpf_dbg.c
index 4f254bc..f715f46 100644
--- a/tools/net/bpf_dbg.c
+++ b/tools/net/bpf_dbg.c
@@ -1213,7 +1213,7 @@ static int cmd_disassemble(char *line_string)
 
 	if (!bpf_prog_loaded())
 		return CMD_ERR;
-	if (strlen(line_string) > 0 &&
+	if (strlen(line_string) > 0 &&)
 	    (line = strtoul(line_string, NULL, 10)) < bpf_prog_len)
 		single_line = true;
 	if (single_line)
-- 
2.1.4

^ permalink raw reply related

* Re: [TSN RFC v2 0/9] TSN driver for the kernel
From: David Miller @ 2016-12-16 18:20 UTC (permalink / raw)
  To: gvrose8192
  Cc: henrik, linux-kernel, richardcochran, haustad, linux-media,
	alsa-devel, netdev
In-Reply-To: <1481911964.3572.1.camel@gmail.com>

From: Greg <gvrose8192@gmail.com>
Date: Fri, 16 Dec 2016 10:12:44 -0800

> On Fri, 2016-12-16 at 18:59 +0100, henrik@austad.us wrote:
>> From: Henrik Austad <haustad@cisco.com>
>> 
>> 
>> The driver is directed via ConfigFS as we need userspace to handle
>> stream-reservation (MSRP), discovery and enumeration (IEEE 1722.1) and
>> whatever other management is needed. This also includes running an
>> appropriate PTP daemon (TSN favors gPTP).
> 
> I suggest using a generic netlink interface to communicate with the
> driver to set up and/or configure your drivers.
> 
> I think configfs is frowned upon for network drivers.  YMMV.

Agreed.

^ permalink raw reply

* Re: [PATCH] bpf: cgroup: annotate pointers in struct cgroup_bpf with __rcu
From: Alexei Starovoitov @ 2016-12-16 18:20 UTC (permalink / raw)
  To: Daniel Mack; +Cc: ast, daniel, netdev, davem
In-Reply-To: <20161215095321.10571-1-daniel@zonque.org>

On Thu, Dec 15, 2016 at 10:53:21AM +0100, Daniel Mack wrote:
> The member 'effective' in 'struct cgroup_bpf' is protected by RCU.
> Annotate it accordingly to squelch a sparse warning.
> 
> Signed-off-by: Daniel Mack <daniel@zonque.org>

Acked-by: Alexei Starovoitov <ast@kernel.org>

was only wondering whether this is really needed for net or can wait till net-next.

> ---
>  include/linux/bpf-cgroup.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
> index 7b6e5d1..92bc89a 100644
> --- a/include/linux/bpf-cgroup.h
> +++ b/include/linux/bpf-cgroup.h
> @@ -20,7 +20,7 @@ struct cgroup_bpf {
>  	 * when this cgroup is accessed.
>  	 */
>  	struct bpf_prog *prog[MAX_BPF_ATTACH_TYPE];
> -	struct bpf_prog *effective[MAX_BPF_ATTACH_TYPE];
> +	struct bpf_prog __rcu *effective[MAX_BPF_ATTACH_TYPE];
>  };
>  
>  void cgroup_bpf_put(struct cgroup *cgrp);
> -- 
> 2.9.3
> 

^ permalink raw reply

* Re: [net-next PATCH v6 0/5] XDP for virtio_net
From: David Miller @ 2016-12-16 18:20 UTC (permalink / raw)
  To: mst
  Cc: john.fastabend, daniel, netdev, alexei.starovoitov,
	john.r.fastabend, brouer, tgraf
In-Reply-To: <20161216011620-mutt-send-email-mst@kernel.org>

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Fri, 16 Dec 2016 01:17:44 +0200

> OK, I think we can queue this for -next.
> 
> It's fairly limited in the kind of hardware supported, we can and
> probably should extend it further with time.
> 
> Acked-by: Michael S. Tsirkin <mst@redhat.com>

Michael, thanks for reviewing.

Since the substance of this patch series has honestly been ready since
before the merge window, would you mind if I send this to Linus now?

That's what I was hoping I would be able to do.

Thanks again.

^ permalink raw reply

* Re: [PATCH] cgroup: Fix CGROUP_BPF config
From: Alexei Starovoitov @ 2016-12-16 18:18 UTC (permalink / raw)
  To: Andy Lutomirski; +Cc: Daniel Mack, Network Development
In-Reply-To: <8d48c3940f8d0275da6398ea5bcef14e20233db5.1481905995.git.luto@kernel.org>

On Fri, Dec 16, 2016 at 08:33:45AM -0800, Andy Lutomirski wrote:
> CGROUP_BPF depended on SOCK_CGROUP_DATA which can't be manually
> enabled, making it rather challenging to turn CGROUP_BPF on.
> 
> Signed-off-by: Andy Lutomirski <luto@kernel.org>

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply

* Re: [PATCH net 1/3] cpsw/netcp: cpts depends on posix_timers
From: Nicolas Pitre @ 2016-12-16 18:18 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: David S. Miller, Grygorii Strashko, Thomas Gleixner, John Stultz,
	Uwe Kleine-König, WingMan Kwok, netdev, linux-kernel
In-Reply-To: <20161216092017.2560717-1-arnd@arndb.de>

On Fri, 16 Dec 2016, Arnd Bergmann wrote:

> With posix timers having become optional, we get a build error with
> the cpts time sync option of the CPSW driver:
> 
> drivers/net/ethernet/ti/cpts.c: In function 'cpts_find_ts':
> drivers/net/ethernet/ti/cpts.c:291:23: error: implicit declaration of function 'ptp_classify_raw';did you mean 'ptp_classifier_init'? [-Werror=implicit-function-declaration]
> 
> It really makes no sense to build this driver if we can't use PTP,
> so it's better to go back to 'select PTP_1588_CLOCK' but instead
> add a dependency on POSIX_TIMERS.

Why not depend on PTP_1588_CLOCK directly instead?

> Fixes: baa73d9e478f ("posix-timers: Make them configurable")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/net/ethernet/ti/Kconfig | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
> index 296c8efd0038..366e29ff8605 100644
> --- a/drivers/net/ethernet/ti/Kconfig
> +++ b/drivers/net/ethernet/ti/Kconfig
> @@ -76,7 +76,8 @@ config TI_CPSW
>  config TI_CPTS
>  	tristate "TI Common Platform Time Sync (CPTS) Support"
>  	depends on TI_CPSW || TI_KEYSTONE_NETCP
> -	imply PTP_1588_CLOCK
> +	depends on POSIX_TIMERS
> +	select PTP_1588_CLOCK
>  	---help---
>  	  This driver supports the Common Platform Time Sync unit of
>  	  the CPSW Ethernet Switch and Keystone 2 1g/10g Switch Subsystem.
> -- 
> 2.9.0
> 
> 

^ permalink raw reply

* Re: [TSN RFC v2 0/9] TSN driver for the kernel
From: Greg @ 2016-12-16 18:12 UTC (permalink / raw)
  To: henrik
  Cc: linux-kernel, Richard Cochran, Henrik Austad, linux-media,
	alsa-devel, netdev
In-Reply-To: <1481911153-549-1-git-send-email-henrik@austad.us>

On Fri, 2016-12-16 at 18:59 +0100, henrik@austad.us wrote:
> From: Henrik Austad <haustad@cisco.com>
> 
> 
> The driver is directed via ConfigFS as we need userspace to handle
> stream-reservation (MSRP), discovery and enumeration (IEEE 1722.1) and
> whatever other management is needed. This also includes running an
> appropriate PTP daemon (TSN favors gPTP).

I suggest using a generic netlink interface to communicate with the
driver to set up and/or configure your drivers.

I think configfs is frowned upon for network drivers.  YMMV.

- Greg

> 
> Once we have all the required attributes, we can create link using
> mkdir, and use write() to set the attributes. Once ready, specify the
> 'shim' (basically a thin wrapper between TSN and another subsystem) and
> we start pushing out frames.
> 
> The network part: it ties directly into the Rx-handler for receive and
> writes skb's using dev_queue_xmit(). This could probably be improved.
> 
> 2 new fields in netdev_ops have been introduced, and the Intel
> igb-driver has been updated (as this an AVB-capable NIC which is
> available as a PCI-e card).
> 
> What remains (tl;dr: a lot) a.k.a "Known problems" or "working on it!"
> - tie to (g)PTP properly, currently using ktime_get() for presentation
>   time
> - get time from shim into TSN
> - let shim create/manage buffer
> - redo parts of the link-stuff using RCUs, the current setup is a bit
>   clumsy.
> - The igb-driver does not work properly when compiled with IGB_TSN, some
>   details in setting the register values needs to be figured out. I am
>   working on this, but as it stands, the best bet is to load tsn using
>   in_debug=1 to bypass the capability-check. I have had e1000 and sky2
>   running for several days without crashing, igb crashes and burns
>   violently.
> - The ALSA driver does not handle multiple devices very well and is a
>   work in progress.
> 
> * v2: changes since v1
> 
> Changes since v1
> - updated to latest upstream kernel (v4.8)
> - set dedicated enabled-attribute and let shim be stored in own (support
>   future plan for enabling per-shim attributes)
> - fixed endianess issue in bitfields used in tsn-structs
> - Updated some of the trace-events to use trace_class
> - Fix various silly typos
> - Handle disabling of link from hrtimer a bit more gracefully (that
>   actually works-ish).
> - use old skb and size of skb when that is set (Reporte by Nikita)
> - Move PCP-codes to NIC and not in the link itself
> - Allow TSN-capable card to be loaded even when in debug-mode (and do
>   not enforce TSN behaviour)
> - Start hooking into ALSA's get_time_info hooks (very much incomplete)
> - use threads for sending frames, wake from hrtimer-callback.
>   This also queues up awaiting timers if we fail to complete the
>   transmit before another timer arrives, it will immediately execute
>   another iteration, so no events should be lost. That being said,
>   should this happen, it is a clear bug as we really should complete
>   well before the next interval.
> - Cleanup link-locking and differentiate between Talker and Listener (as
>   Listener grab link-lock from IRQ context)
> - Change list-lock to spinlock as we may need to take a link-lock whilst
>   holding the master list-lock.
> - Do a more careful dance holding the spinlocks to regions only doing
>   actual update.
> 
> Network driver (I210 only)
> - bring up all Tx-/Rx-queues when igb is in TSN-mode regardless of how
>   many CPUs the system has for I210
> - Correctly calculate the idle_slope in I210's configure hook
> - Update igb-driver with queue-select and return correct queue when
>   sending TSN-frames
> - add IGB_FLAG_QAV_PRIO flag to igb_adapter (to handle proper config of
>   tx-ring when adapter is brought up.
> - add TXDCTL logic (part of preparatory work for TSN) to igb-driver
> - Improve SR(A|B) accountingo
> 
> ALSA Shim
> - Allow userspace to grab much smaller chunks of data (down to a single
>   Class A frame for S16_LE 2ch 48kHz).
> - Create the card with index/id pattern to avoid collision with other
>   cards.
> * v1
> 
> Before reading on - this is not even beta, but I'd really appreciate if
> people would comment on the overall architecture and perhaps provide
> some pointers to where I should improve/fix/update
> - thanks!
> 
> This is a very early RFC for a TSN-driver in the kernel. It has been
> floating around in my repo for a while and I would appreciate some
> feedback on the overall design to avoid doing some major blunders.
> 
> There are at least one AVB-driver (the AV-part of TSN) in the kernel
> already. This driver aims to solve a wider scope as TSN can do much more
> than just audio. A very basic ALSA-driver is added to the end that
> allows you to play music between 2 machines using aplay in one end and
> arecord | aplay on the other (some fiddling required) We have plans for
> doing the same for v4l2 eventually (but there are other fishes to fry
> first). The same goes for a TSN_SOCK type approach as well.
> 
> Henrik Austad (9):
>   igb: add missing fields to TXDCTL-register
>   TSN: add documentation
>   TSN: Add the standard formerly known as AVB to the kernel
>   Adding TSN-driver to Intel I210 controller
>   Add TSN header for the driver
>   Add TSN machinery to drive the traffic from a shim over the network
>   Add TSN event-tracing
>   AVB ALSA - Add ALSA shim for TSN
>   MAINTAINERS: add TSN/AVB-entries
> 
>  Documentation/TSN/tsn.txt                    |  345 ++++++++
>  MAINTAINERS                                  |   14 +
>  drivers/media/Kconfig                        |   15 +
>  drivers/media/Makefile                       |    2 +-
>  drivers/media/avb/Makefile                   |    5 +
>  drivers/media/avb/avb_alsa.c                 |  793 +++++++++++++++++
>  drivers/media/avb/tsn_iec61883.h             |  152 ++++
>  drivers/net/ethernet/intel/Kconfig           |   18 +
>  drivers/net/ethernet/intel/igb/Makefile      |    2 +-
>  drivers/net/ethernet/intel/igb/e1000_82575.h |    4 +
>  drivers/net/ethernet/intel/igb/igb.h         |   26 +
>  drivers/net/ethernet/intel/igb/igb_main.c    |   39 +-
>  drivers/net/ethernet/intel/igb/igb_tsn.c     |  468 ++++++++++
>  include/linux/netdevice.h                    |   44 +
>  include/linux/tsn.h                          |  952 +++++++++++++++++++++
>  include/trace/events/tsn.h                   |  333 ++++++++
>  net/Kconfig                                  |    1 +
>  net/Makefile                                 |    1 +
>  net/tsn/Kconfig                              |   32 +
>  net/tsn/Makefile                             |    6 +
>  net/tsn/tsn_configfs.c                       |  673 +++++++++++++++
>  net/tsn/tsn_core.c                           | 1189 ++++++++++++++++++++++++++
>  net/tsn/tsn_header.c                         |  162 ++++
>  net/tsn/tsn_internal.h                       |  397 +++++++++
>  net/tsn/tsn_net.c                            |  392 +++++++++
>  25 files changed, 6061 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/TSN/tsn.txt
>  create mode 100644 drivers/media/avb/Makefile
>  create mode 100644 drivers/media/avb/avb_alsa.c
>  create mode 100644 drivers/media/avb/tsn_iec61883.h
>  create mode 100644 drivers/net/ethernet/intel/igb/igb_tsn.c
>  create mode 100644 include/linux/tsn.h
>  create mode 100644 include/trace/events/tsn.h
>  create mode 100644 net/tsn/Kconfig
>  create mode 100644 net/tsn/Makefile
>  create mode 100644 net/tsn/tsn_configfs.c
>  create mode 100644 net/tsn/tsn_core.c
>  create mode 100644 net/tsn/tsn_header.c
>  create mode 100644 net/tsn/tsn_internal.h
>  create mode 100644 net/tsn/tsn_net.c
> 
> --
> 2.7.4

^ permalink raw reply

* Re: [PATCH 1/2] bpf: do not use KMALLOC_SHIFT_MAX
From: Alexei Starovoitov @ 2016-12-16 18:02 UTC (permalink / raw)
  To: Michal Hocko
  Cc: linux-mm, Cristopher Lameter, Andrew Morton, Michal Hocko,
	Alexei Starovoitov, netdev, Daniel Borkmann
In-Reply-To: <20161215164722.21586-2-mhocko@kernel.org>

On Thu, Dec 15, 2016 at 05:47:21PM +0100, Michal Hocko wrote:
> From: Michal Hocko <mhocko@suse.com>
> 
> 01b3f52157ff ("bpf: fix allocation warnings in bpf maps and integer
> overflow") has added checks for the maximum allocateable size. It
> (ab)used KMALLOC_SHIFT_MAX for that purpose. While this is not incorrect
> it is not very clean because we already have KMALLOC_MAX_SIZE for this
> very reason so let's change both checks to use KMALLOC_MAX_SIZE instead.
> 
> Cc: Alexei Starovoitov <ast@kernel.org>
> Signed-off-by: Michal Hocko <mhocko@suse.com>

Nack until the patches 1 and 2 are reversed.

The bug that patch 2 fixes was the reason we used KMALLOC_SHIFT_MAX - 1 here
instead of KMALLOC_MAX_SIZE,
so you have to fix the kmalloc vs __alloc_pages_slowpath discrepancy first.

> ---
>  kernel/bpf/arraymap.c | 2 +-
>  kernel/bpf/hashtab.c  | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
> index a2ac051c342f..229a5d5df977 100644
> --- a/kernel/bpf/arraymap.c
> +++ b/kernel/bpf/arraymap.c
> @@ -56,7 +56,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
>  	    attr->value_size == 0 || attr->map_flags)
>  		return ERR_PTR(-EINVAL);
>  
> -	if (attr->value_size >= 1 << (KMALLOC_SHIFT_MAX - 1))
> +	if (attr->value_size > KMALLOC_MAX_SIZE)
>  		/* if value_size is bigger, the user space won't be able to
>  		 * access the elements.
>  		 */
> diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
> index ad1bc67aff1b..c5ec7dc71c84 100644
> --- a/kernel/bpf/hashtab.c
> +++ b/kernel/bpf/hashtab.c
> @@ -181,7 +181,7 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
>  		 */
>  		goto free_htab;
>  
> -	if (htab->map.value_size >= (1 << (KMALLOC_SHIFT_MAX - 1)) -
> +	if (htab->map.value_size >= KMALLOC_MAX_SIZE -
>  	    MAX_BPF_STACK - sizeof(struct htab_elem))
>  		/* if value_size is bigger, the user space won't be able to
>  		 * access the elements via bpf syscall. This check also makes
> -- 
> 2.10.2
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH v5 1/4] siphash: add cryptographically secure PRF
From: Jason A. Donenfeld @ 2016-12-16 18:00 UTC (permalink / raw)
  To: George Spelvin
  Cc: Jean-Philippe Aumasson, Andi Kleen, David Miller, David Laight,
	Daniel J . Bernstein, Eric Biggers, Hannes Frederic Sowa,
	kernel-hardening, Linux Crypto Mailing List, LKML,
	Andy Lutomirski, Netdev, Tom Herbert, Linus Torvalds,
	Theodore Ts'o, Vegard Nossum
In-Reply-To: <20161216173624.21544.qmail@ns.sciencehorizons.net>

Hi George,

On Fri, Dec 16, 2016 at 6:36 PM, George Spelvin
<linux@sciencehorizons.net> wrote:
> A 128-bit output option was added to SipHash after the initial publication;
> this is just the equivalent in 32-bit.
> Personally, I'd put in a comment saying that "there's a 64-bit output
> variant that's not implemented" and punt until someone find a need.

That's a good way to think about it. Okay, I'll do precisely that.

> On a 64-bit machine, 64-bit SipHash is *always* faster than 32-bit, and
> should be used always.  Don't even compile the 32-bit code, to prevent
> anyone accidentally using it, and make hsiphash an alias for siphash.

Fascinating! Okay. So I'll alias hsiphash to siphash on 64-bit then. I
like this arrangement.


> Fortunately, the cost of brute-forcing hash functions can be fairly
> exactly quantified, thanks to bitcoin miners.  It currently takes 2^70
> hashes to create one bitcoin block, worth 25 bitcoins ($19,500).  Thus,
> 2^63 hashes cost $152.
>
> Now, there are two factors that must be considered:
> - That's a very very "wholesale" rate.  That's assuming you're doing
>   large numbers of these and can put in the up-front effort designing
>   silicon ASICs to do the attack.
> - That's for a more difficult hash (double sha-256) than SipHash.
>   That's a constant fator, but a pretty significant one.  If the wholesale
>   assumption holds, that might bring the cost down another 6 or 7 bits,
>   to $1-2 per break.
>
> If you're not the NSA and limited to general-purpose silicon, let's
> assume a state of the art GPU (Radeon HD 7970; AMD GPUs seem do to better
> than nVidia).  The bitcoin mining rate for those is about 700M/second,
> 29.4 bits.  So 63 bits is 152502 GPU-days, divided by some factor
> to account for SipHash's high speed compared to two rounds of SHA-2.
> Call it 1000 GPU-days.
>
> It's very doable, but also very non-trivial.  The question is, wouldn't
> it be cheaper and easier just to do a brute-force flooding DDoS?
>
> (This is why I wish the key size could be tweaked up to 80 bits.
> That would take all these numbers out of the reasonable range.)

That's a nice analysis. Might one conclude from that that hsiphash is
not useful for our purposes? Or does it still remain useful for
network facing code?

> Let me consider your second example above, "secure against local users".
> I should dig through your patchset and find the details, but what exactly
> are the consequences of such an attack?  Hasn't a local user already
> got much better ways to DoS the system?

For example, an unpriv'd user putting lots of entries in one hash
bucket for a shared resource that's used by root, like filesystems or
other lookup tables. If he can cause root to use more of root's cpu
schedule budget than otherwise in a directed way, then that's a bad
DoS.

> The thing to remember is that we're worried only about the combination
> of a *new* Linux kernel (new build or under active maintenance) and a
> 32-bit host.  You'd be hard-pressed to find a *single* machine fitting
> that description which is hosting multiple users or VMs and is not 64-bit.
>
> These days, 32-bit CPUs are for embedded applications: network appliances,
> TVs, etc.  That means basically single-user.  Even phones are 64 bit.
> Is this really a threat that needs to be defended against?

I interpret this to indicate all the more reason to alias hsiphash to
siphash on 64-bit, and then the problem space collapses in a clear
way.

> For your first case, network applications, the additional security
> is definitely attractive.  Syncookies are only a DoS, but sequence
> numbers are a real security issue; they can let you inject data into a
> TCP connection.
> With sequence numbers, large amounts (32 bits) the hash output is
> directly observable.

Right. Hence the need for always using full siphash and not hsiphash
for sequence numbers, per my earlier email to David.

>
> I wish we could get away with 64-bit security, but given that the
> modern internet involves attacks from NSA/Spetssvyaz/3PLA, I agree
> it's just not enough.

I take this comment to be relavent for the sequence number case.

For hashtables and hashtable flooding, is it still your opinion that
we will benefit from hsiphash? Or is this final conclusion a rejection
of hsiphash for that too? We're talking about two different use cases,
and your email kind of interleaved both into your analysis, so I'm not
certain so to precisely what your conclusion is for each use case. Can
you clear up the ambiguity?

Jason

^ permalink raw reply

* [TSN RFC v2 9/9] MAINTAINERS: add TSN/AVB-entries
From: henrik @ 2016-12-16 17:59 UTC (permalink / raw)
  To: linux-kernel
  Cc: Richard Cochran, henrik, Henrik Austad, linux-media, alsa-devel,
	netdev
In-Reply-To: <1481911153-549-1-git-send-email-henrik@austad.us>

From: Henrik Austad <haustad@cisco.com>

Not sure how relevant this is other than making a point about
maintaining it.

Signed-off-by: Henrik Austad <haustad@cisco.com>
---
 MAINTAINERS | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 63cefa6..7c5afd2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12295,6 +12295,20 @@ T:	git git://linuxtv.org/anttip/media_tree.git
 S:	Maintained
 F:	drivers/media/tuners/tua9001*
 
+TSN CORE DRIVER
+M:	Henrik Austad <haustad@cisco.com>
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	drivers/net/tsn/
+F:	include/linux/tsn.h
+F:	include/trace/events/tsn.h
+
+TSN_AVB_DRIVER
+M:	Henrik Austad <haustad@cisco.com>
+L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
+S:	Supported
+F:	drivers/media/avb/
+
 TULIP NETWORK DRIVERS
 L:	netdev@vger.kernel.org
 L:	linux-parisc@vger.kernel.org
-- 
2.7.4

^ permalink raw reply related

* [TSN RFC v2 2/9] TSN: add documentation
From: henrik @ 2016-12-16 17:59 UTC (permalink / raw)
  To: linux-kernel
  Cc: Richard Cochran, henrik, Henrik Austad, linux-media, alsa-devel,
	netdev, David S. Miller
In-Reply-To: <1481911153-549-1-git-send-email-henrik@austad.us>

From: Henrik Austad <haustad@cisco.com>

Describe the overall design behind the TSN standard, the TSN-driver,
requirements to userspace and new functionality introduced.

Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Henrik Austad <haustad@cisco.com>
---
 Documentation/TSN/tsn.txt | 345 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 345 insertions(+)
 create mode 100644 Documentation/TSN/tsn.txt

diff --git a/Documentation/TSN/tsn.txt b/Documentation/TSN/tsn.txt
new file mode 100644
index 0000000..540246f
--- /dev/null
+++ b/Documentation/TSN/tsn.txt
@@ -0,0 +1,345 @@
+                Time Sensitive Networking (TSN)
+                -------------------------------
+
+[work in progress]
+
+1. Motivation
+=============
+
+TSN is a set of open standards, formerly known as 'AVB' (Audio/Video
+Bridging). It was renamed to TSN to better reflect that it can do much
+more than just media transport and extended to handle more types of
+traffic.
+
+TSN is a way to create reliable, deterministic streams across a network
+without loss of frames due to congestion in the network. By using gPTP
+(a specialized IEEE-1588v2 PTP profile), the time can be synchronized
+with sub-us granularity across all the connected devices in the AVB
+domain.
+
+In its current version, this driver only supports L2 traffic (i.e
+etherframes only), but later version is planned to handle L3. L2-L3
+traversing is currently being worked on by the IETF detnet working
+group.
+
+2. Intro to AVB/TSN
+===================
+
+The original standards were written with Audio/Video in mind, so the
+initial standards refer to this as 'AVB'. In later standards, this has
+changed to TSN, and AVB now refers to a service you can add on top of
+TSN. In some parts of the driver, this naming shines through, in
+particular for AVTP (AVB Transport Protocol), and this is to reflect the
+naming in the standards.
+
+In this document, we refer to the infrastructure part as TSN, and AVB to
+the ALSA/V4L2 shim which can be added on top of TSN to provide a
+media-service.
+
+TSN operates with 'streams', and one stream can contain pretty much
+whatever you like. An AVB stream carrying audio can carry multiple
+channels. The current revision of AVTP (defined in IEEE 1722 d16)
+defines many more types than media.
+
+A stream flows through the network from a Talker to a Listener. A Talker
+is a single End-station in the network, a Listener can be a single
+End-station (unicast) or a group of end-stdations (multicast).
+
+2.1 Domains
+
+2.1.1 SRP Domain
+
+An SRP domain is the set of entities in the network that support the
+Stream Reservation Protocol (IEEE 802.1Q-2014 Sec 35) and where all
+entities agree on the priority code points (PCP). A bridge will mark
+each port as either SRP capable or not capable.
+
+PCP is used to map a specific priority to a given traffic-class,
+typically class A or B.
+
+2.1.2 gPTP domain
+
+This is the set of all connected bridges and end-stations that support
+the gPTP protocol. gPTO is a PTPv2 profile.
+
+2.1.3 AVB Domain
+
+An AVB domain is the intersection of an SRP Domain and gPTP domain.
+
+
+2.2 End Station (ES)
+
+An TSN ES is where a stream either originates or ends -what others would
+call sources (Talkers) and sinks (Listeners). Looking back at pre-TSN
+when this was called AVB, these names make a bit more sense.
+
+Common for both types, they need to be PTPv2 capable, i.e. you need to
+timestamp gPTP frames upon ingress/egress to improve the accuracy of
+PTP.
+
+2.2.1 Talkers
+
+A Talker must be single ES in the AVB Domain.
+
+Hardware requirements:
+- Multiple Tx-queues
+- Credit based shaper on at least one of the queues for pacing the
+  frames onto the network
+- VLAN capable
+
+2.2.2 Listener
+
+A Listener does not have the same requirements as a Talker as it cannot
+control the pace of the incoming frames anyway. It is beneficial if the
+NIC understands VLANs and has a few Rx-queues so that you can steer all
+TSN-frames to a dedicated queue, but this is not a hard requirement.
+
+If the Listener receives audio, having an adjustable PL/L is a clear
+benefit to avoid resampling.
+
+2.3 Bridges
+
+A Bridge is what TSN calls switches that are TSN-capable. They must be
+able to prioritize TSN-streams, have the credit-based shaper available
+for that class, support SRP, support gPTP and so on. The requirements is
+laid down in "Forwardin and Queueing of Time Sensitive Streams" (IEEE
+802.1Q-2014 sec. 34).
+
+2.4 Relevant standards
+
+* IEEE 802.1BA-2011 Audio Video Bridging (AVB) Systems
+
+* IEEE 802.1Q-2014 sec 34 and 35
+
+  What is referred to as:
+  IEEE 802.1Qav (Forwarding and Queueing for Time-sensitive Streams)
+  IEEE 802.1Qat (Stream Registration protocol)
+
+* IEEE 802.1AS gPTP
+
+  A PTPv2 profile (from IEEE 1588) tailored for this domain. Notable
+  changes include the requirement that all nodes in the network must be
+  gPTP capable (i.e. no traversing non-PTP entities), and it allows
+  traffic over a wider range of medium that what "pure" PTPv2 allows.
+
+* IEEE 1722 AVTP Layer 2 Transport Protocol for Time-Sensitive
+  Applications in Bridged Local Area Networks
+  Further improvements in IEEE 1722.d16-2015.
+
+* IEEE 1722.1 Device Discovery, Connection Management and Control for 1722
+
+  What allows AVB (TSN) devices to handle discovery, enumeration and
+  control, basically let you connect 2 devices from a 3rd
+
+  In this (in the scope of the Linux kernel TSN driver) must be done
+  purely from userspace as we do not want the kernel to suddenly attach
+  to a remote system without the user's knowledge. This is further
+  reflected in how the attributes for the link is managed via ConfigFS.
+
+
+3. Overview and/or design of the TSN-driver
+===========================================
+
+The driver handles the shifting of data for TSN-streams. Anything else
+is left for userspace to handle. This includes stream reservation (using
+some sort of MSRP client), negotiating multicast addresses, finding the
+value of the different attributes and connect application(s) to the
+exposed devices (currently we only have an ALSA-device via the AVB ALSA
+Shim).
+
+Note: the kernel-driver for TSN is tsn (lowercase). When we refer to the
+_standard_ TSN, we use uppercase. Hopefully this won't be too confusing.
+
+               /--------------------\
+               |                    |
+               |  Media application |
+               |                    |
+               \--------------------/
+                     |        |
+          +----------+        +----+
+          |                        |
+          |                        |
+     +------------+                |
+     |   ALSA     |                |
+     +------------+                |
+          |                        |
+          |                        |
+     +------------+          +--------------+
+     |  avb_alsa  |          | tsn_configfs |
+     | (tsn-shim) |          +--------------+
+     +------------+                |
+          |                        |
+          |                        |
+          +------+                 |
+                 |                 |
+                 |                 |
+            +------------+         |
+            |  tsn_core  |<--------+
+            +------------+
+                 |
+                 |
+            +------------+
+            |  tsn_net   |
+            +------------+
+                 |
+                 |
+            +------------+
+            |  network   |
+            | subsystem  |
+            +------------+
+                 |
+                 |
+                ...
+
+
+3.1 Terms and concepts
+
+tsn uses the concept of streams and shims.
+
+- A shim is a thin wrapper that binds TSN to another subsystem (or
+  directly to userspace). avb_alsa is an example of such a shim.
+
+- A stream is the only data TSN cares about. What the data inside the
+  stream represents, is left for the associated shim to handle. TSN will
+  verify the headers up to the protocol specific header and then pass it
+  along to the shim.
+
+Note: currently, only the data-unit part is implemented, the control
+part, in which 1722.1 (discovery and enumeration) is part, is not
+handled.
+
+3.2 Userspace requirements
+
+(msrp-client, "tsnctl"-tool
+
+4. ConfigFS overview
+=====================================
+
+4.1 Global attributes
+
+4.1.1 available_shims
+
+Read-only, lists all shims that has been loaded. When no shims has been
+loaded, 'none' is the only available.
+
+e.g.
+     /config/tsn# cat available_shims
+     none
+     alsa
+
+
+4.1.2 stream_ids
+
+Read-only, list of all StreamIDs used by the links. This is for _all_
+links on all NICs. Even if 2 NICs are on separate networks and therefore
+in theory have identical stream_id, we do a global approach.
+
+
+4.2 Per NIC attributes
+
+4.2.1  pcp_a
+
+Priority Code Point, class A. This must be the same for all streams in
+a AVB-domain, and a NIC can only partake in one.
+
+4.2.2  pcp_b
+
+Priority Code Point, class B
+
+4.2.3 list of NICs
+
+Each TSN-capable NIC is listed as a directory, inside each NIC it is
+possible to instantiate a new link using mkdir.
+
+4.3 Per stream attributes
+
+The value of the per-stream attributes need to be coordinated with the
+network. Many of these can/must be found using MSRP during link
+negotiation. The TSN driver expects userspace to do all the reservation
+so that when the link is set to active, the network will accept the
+outgoing frames.
+
+4.3.1  buffer_size
+
+Size (in kB) of the buffer the shim will use to store data before
+packing it into frames and sending (or storing incoming data in).
+
+4.3.2  class
+
+TSN splits traffic in 2 class, class A and B, 'A' or 'B' will signal
+which class this link belongs to.
+
+4.3.3  enabled
+
+'on' or 'off', indicating that the link is currently not pushing data or
+that it is fully configured and is pushing data over the network.
+
+Only valid options are 'on' and 'off' (lowercase only).
+
+4.3.4  end_station
+
+'Talker' or 'Listener'. A link cannot be both. It either sends (Talker)
+or receives (Listener) data.
+
+4.3.5  local_mac
+
+MAC address that receives data for this link. Currently this is the MAC
+for the NIC, in theory it could be a multicast address (not supported
+right now).
+
+4.3.6  max_payload_size
+
+Upper bound on how much data will be pushed in each frame. A shim can
+send _less_ than this, but never more. This is due to bandwidth
+reservation constraints.
+
+4.3.7 remote_mac
+
+Destination for L2-traffic.
+
+4.3.8 shim
+
+Shim registered to this link. 'None' means no shim, and the link cannot
+be set to active. Valid shims are listed in the global
+'available_shims' (see 4.1.1).
+
+4.3.9 shim_header_size
+
+A shim will most likely need some header to go along with the data. This
+indicates to tsn how large the header is so that frame-size constraints
+can be respected.
+
+4.3.10 stream_id
+
+StreamID for the stream this link runs. Must be globally unique on the
+host, see 4.1.2.
+
+4.3.11 vlan_id
+
+TSN does not really care about the VLAN ID, but the network may care a
+whole lot. This sets the VLAN ID to use for the traffic belonging to
+this link.
+
+
+5. Creating a new TSN Link from userspace
+=====================================
+
+A link is created in multiple steps.
+
+1. Create space for the link:
+   mkdir /config/tsn/eth0/link
+
+2. Sett values for the attributes for the link
+
+
+6. Creating a new shim
+======================
+
+shim_ops
+[coming]
+
+
+7. Other resources:
+===================
+
+https://en.wikipedia.org/wiki/Audio_Video_Bridging
-- 
2.7.4

^ permalink raw reply related

* [TSN RFC v2 8/9] AVB ALSA - Add ALSA shim for TSN
From: henrik @ 2016-12-16 17:59 UTC (permalink / raw)
  To: linux-kernel
  Cc: Richard Cochran, henrik, Henrik Austad, linux-media, alsa-devel,
	netdev, Mauro Carvalho Chehab, Takashi Iwai, Mark Brown
In-Reply-To: <1481911153-549-1-git-send-email-henrik@austad.us>

From: Henrik Austad <haustad@cisco.com>

This exposes a *very* rudimentary and simplistic ALSA driver that hooks
into TSN to create a device for userspace.

It currently only supports 44.1/48kHz sampling, 2ch, S16_LE

Userspace is supposed to reserve bandwidth, find StreamID etc.

To use as a Talker:

mkdir /config/tsn/test/eth0/talker
cd /config/tsn/test/eth0/talker
echo 65535 > buffer_size
echo 08:00:27:08:9f:c3 > remote_mac
echo 42 > stream_id
echo alsa > shim
echo on > enabled

     aplay -Ddefault:CARD=avb music.wav

  or

     arecord -r48000 -c2 -f S16_LE | aplay -Ddefault:CARD=avb

alternatively, if the device is set as Listener;

     arecord -r48000 -c2 -f S16_LE -Ddefault:CARD=avb > file.wav

Cc: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Cc: Takashi Iwai <tiwai@suse.de>
Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Henrik Austad <haustad@cisco.com>
---
 drivers/media/Kconfig            |  15 +
 drivers/media/Makefile           |   2 +-
 drivers/media/avb/Makefile       |   5 +
 drivers/media/avb/avb_alsa.c     | 793 +++++++++++++++++++++++++++++++++++++++
 drivers/media/avb/tsn_iec61883.h | 152 ++++++++
 5 files changed, 966 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/avb/Makefile
 create mode 100644 drivers/media/avb/avb_alsa.c
 create mode 100644 drivers/media/avb/tsn_iec61883.h

diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 7b85402..8250aff 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -221,3 +221,18 @@ source "drivers/media/tuners/Kconfig"
 source "drivers/media/dvb-frontends/Kconfig"
 
 endif # MEDIA_SUPPORT
+
+config MEDIA_AVB_ALSA
+       tristate "ALSA part of AVB over TSN"
+       depends on TSN
+       help
+
+         Enable the ALSA device that hoooks into TSN and allows the
+         computer to send ethernet frames over the network carrying
+         audio-data to selected hosts.
+
+	 This must be configured by userspace as MSRP and IEEE 1722.1
+	 (discovery and enumeration) is not implemented within the
+	 kernel.
+
+	 If unsure, say N
\ No newline at end of file
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 0deaa93..9dfee62 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -34,4 +34,4 @@ obj-y += rc/
 
 obj-y += common/ platform/ pci/ usb/ mmc/ firewire/ spi/
 obj-$(CONFIG_VIDEO_DEV) += radio/
-
+obj-$(CONFIG_MEDIA_AVB_ALSA) += avb/
diff --git a/drivers/media/avb/Makefile b/drivers/media/avb/Makefile
new file mode 100644
index 0000000..5d6302c
--- /dev/null
+++ b/drivers/media/avb/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the ALSA shim in AVB/TSN
+#
+
+obj-$(CONFIG_MEDIA_AVB_ALSA) += avb_alsa.o
diff --git a/drivers/media/avb/avb_alsa.c b/drivers/media/avb/avb_alsa.c
new file mode 100644
index 0000000..bd202f5
--- /dev/null
+++ b/drivers/media/avb/avb_alsa.c
@@ -0,0 +1,793 @@
+/* Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights
+ * reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <linux/platform_device.h>
+#include <sound/pcm_params.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <linux/tsn.h>
+#include "tsn_iec61883.h"
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for AVB soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for AVB soundcard.");
+
+struct avb_chip {
+	struct snd_card *card;
+	struct tsn_link *link;
+	struct snd_pcm *pcm;
+	struct snd_pcm_substream *substream;
+
+	/* Need a reference to this when we unregister the platform
+	 * driver.
+	 */
+	struct platform_device *device;
+
+	/* on first copy, we set a few values, use this to make sure we
+	 * only do this once.
+	 */
+	u8 first_copy;
+
+	u8 sample_size;
+	u8 channels;
+
+	/* current idx in 10ms set of frames
+	 * class A: 80
+	 * class B: 40
+	 *
+	 * This is mostly relevant for 44.1kHz samplefreq
+	 */
+	u8 num_10ms_series;
+
+	u32 sample_freq;
+};
+
+/* currently, only playback is implemented in TSN layer
+ *
+
+ * FIXMEs: (should be set according to the active TSN link)
+ * - format
+ * - rates
+ * - channels
+ *
+ * report absolute hardware link audio time, not reset on startup
+ * (SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME). We are using gPTP time for
+ * arrival/transmit of frames, this will be handled by
+ * tsn_(read|write)_buffer_net()
+ */
+static struct snd_pcm_hardware snd_avb_hw = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+	.rate_min = 44100,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* we currently expect either class A or B, where A has the
+	 * smallest frames. For 44.1, you can get 11 sample-sets in one
+	 * frame, and for 2ch S16_LE, this gives us 44 bytes.
+	 */
+	.period_bytes_min = 44,
+	.period_bytes_max = 32768,
+	.buffer_bytes_max = 32768,
+	.periods_min = 1,
+	.periods_max = 1024,
+	.fifo_size   = 0,
+};
+
+static size_t snd_avb_copy_size(struct tsn_link *link);
+
+
+static int _set_chip_values(struct avb_chip *avb_chip,
+			struct snd_pcm_runtime *runtime)
+{
+	if (!avb_chip->first_copy)
+		return 0;
+
+
+	/*
+	 * first copy, we now know that runtime has all the correct
+	 * values set, we can grab channels and rate. Sample_size
+	 * (runtime->format) is currently hard-coded to S16_LE.
+	 */
+	avb_chip->channels = runtime->channels;
+	avb_chip->sample_freq = runtime->rate;
+	avb_chip->sample_size = 16;
+
+	if (snd_avb_copy_size(avb_chip->link) > avb_chip->link->max_payload_size) {
+		pr_err("%s: Resulting payload-size is larger (%zd) than available (%u)\n",
+			__func__, snd_avb_copy_size(avb_chip->link),
+			avb_chip->link->max_payload_size);
+		return -EINVAL;
+	}
+	avb_chip->first_copy = 0;
+	return 0;
+}
+
+static int _snd_avb_open(struct avb_chip *avb_chip,
+			struct snd_pcm_runtime *runtime)
+{
+	/*
+	 * We do not know what some of these values are until we see the
+	 * first copy. We set to sane defaults where we don't have exact
+	 * content.
+	 */
+	avb_chip->channels = 0;
+	avb_chip->sample_size = 0;
+	avb_chip->sample_freq = 0;
+	avb_chip->num_10ms_series = 0;
+	avb_chip->first_copy = 1;
+
+	runtime->hw = snd_avb_hw;
+	runtime->buffer_size = avb_chip->link->buffer_size;
+	return 0;
+}
+
+/*
+ * bytes_to_frames()
+ * frames_to_bytes()
+ *
+ * frames_to_bytes(runtime, runtrime->period_size);
+ *
+ * Interrupt callbacks:
+ * The field traonsfer_ack_begin and transfer_ack_end are called at the
+ * beginning and at the end of snd_pcm_period_elapsed(), respectively.
+ */
+static int snd_avb_playback_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+	int ret = 0;
+
+	/*
+	 * we've opened the PCM before probe returned properly and
+	 * stored link in the struct.
+	 */
+	if (!avb_chip || !avb_chip->link) {
+		pr_err("%s: Chip-data or link not available, cannot continue\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (!avb_chip->link->estype_talker) {
+		pr_info("Link (%llu) not registered as Talker, cannot do playback\n",
+			avb_chip->link->stream_id);
+		return -EINVAL;
+	}
+
+	ret = _snd_avb_open(avb_chip, runtime);
+	if (ret < 0) {
+		pr_err("%s: Could not open playback-device (requested %d ch, %zd buffer)",
+			__func__, avb_chip->channels,
+			avb_chip->link->buffer_size);
+		return ret;
+	}
+	pr_info("%s: %d channel PCM stream opened successfully, buffersize: %zd\n",
+		__func__, avb_chip->channels, avb_chip->link->buffer_size);
+	return 0;
+}
+
+static int snd_avb_playback_close(struct snd_pcm_substream *substream)
+{
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+
+	tsn_lb_disable(avb_chip->link);
+
+	pr_info("%s: something happened\n", __func__);
+	return 0;
+}
+
+/*
+ * snd_avb snd_avb.0: BUG: ,
+ *		      pos = 12288,
+ *		      buffer size = 8192,
+ *		      period size = 2048
+ *
+ * Playback is when we *send* data to a remote speaker
+ */
+static int snd_avb_playback_copy(struct snd_pcm_substream *substream,
+				int channel,
+				snd_pcm_uframes_t pos,
+				void *src,
+				snd_pcm_uframes_t count)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+	size_t bytes;
+	int ret;
+
+	/*
+	 * From alsadoc:
+	 *
+	 * You need to check the channel argument, and if it's -1, copy
+	 * the whole channels. Otherwise, you have to copy only the
+	 * specified channel. Please check isa/gus/gus_pcm.c as an
+	 * example.
+	 */
+	if (channel != -1) {
+		pr_err("%s: partial copy not supportet\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = _set_chip_values(avb_chip, runtime);
+	if (ret != 0)
+		return ret;
+
+	bytes = frames_to_bytes(runtime, count);
+	ret = tsn_buffer_write(avb_chip->link, src, bytes);
+	if (ret != bytes) {
+		pr_err("%s: Incorrect copy (%zd, %d) corruption possible\n",
+		       __func__, bytes, ret);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int snd_avb_capture_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+	int ret = 0;
+
+	if (!avb_chip || !avb_chip->link) {
+		pr_err("%s: Chip-data or link not available, cannot continue\n",
+		       __func__);
+		return -EINVAL;
+	}
+	if (avb_chip->link->estype_talker) {
+		pr_info("Link (%llu) registered as Talker, cannot capture\n",
+			avb_chip->link->stream_id);
+		return -EINVAL;
+	}
+	ret = _snd_avb_open(avb_chip, runtime);
+	if (ret < 0) {
+		pr_err("%s: Could not open capture-device (requested %d ch, %zd buffer)",
+			__func__, avb_chip->channels,
+			avb_chip->link->buffer_size);
+		return ret;
+	}
+	tsn_lb_enable(avb_chip->link);
+	pr_info("%s: %d channel PCM stream opened successfully, buffersize: %zd\n",
+		__func__, avb_chip->channels, avb_chip->link->buffer_size);
+	return 0;
+}
+
+static int snd_avb_capture_close(struct snd_pcm_substream *substream)
+{
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+
+	if (!avb_chip || !avb_chip->link)
+		return -EINVAL;
+	pr_err("%s: closing stream\n", __func__);
+
+	tsn_lb_disable(avb_chip->link);
+
+	return 0;
+}
+
+static int snd_avb_capture_copy(struct snd_pcm_substream *substream,
+				int channel,
+				snd_pcm_uframes_t pos,
+				void *src,
+				snd_pcm_uframes_t count)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+	size_t bytes;
+	int ret;
+
+	bytes = frames_to_bytes(runtime, count);
+	ret = tsn_buffer_read(avb_chip->link, src, bytes);
+	if (ret != bytes) {
+		pr_err("%s: incorrect copy (%zd, %d), corrupt capture possible\n",
+			__func__, bytes, ret);
+		tsn_lb_disable(avb_chip->link);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int snd_avb_silence(struct snd_pcm_substream *substream,
+				int channel, snd_pcm_uframes_t pos,
+				snd_pcm_uframes_t count)
+{
+	/* FIXME, should do more than nothing */
+	return 0;
+}
+
+/*
+ * Called when the client defines buffer_size, period_size, format etc
+ * for the pcm substream.
+ *
+ * This is where link->buffer is allocated and link->buffer_size is
+ * defined.
+ *
+ * We are called in the beginning of snd_pcm_hw_params in
+ * sound/core/pcm_native.c, we cannot override runtime-values as they
+ * are updated from hw_params.
+ */
+static int snd_avb_pcm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *hw_params)
+{
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+	unsigned int bsize = params_buffer_bytes(hw_params);
+	int ret = 0;
+
+	/* We need this reference for the refill callback so that we can
+	 * call snd_pcm_period_elapsed();
+	 */
+	avb_chip->substream = substream;
+	ret = tsn_set_buffer_size(avb_chip->link, bsize);
+	if (ret < 0) {
+		pr_err("%s: could not set buffer_size (alsa requested too large? (%d)\n",
+			__func__, ret);
+		goto out;
+	}
+
+	avb_chip->num_10ms_series = 0;
+	pr_info("%s: successfully set hw-params\n", __func__);
+out:
+	return ret;
+}
+
+static int snd_avb_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+
+	if (!avb_chip || !avb_chip->link)
+		return -EINVAL;
+	tsn_clear_buffer_size(avb_chip->link);
+	pr_info("%s: something happened\n", __func__);
+	avb_chip->substream = NULL;
+	return 0;
+}
+
+static int snd_avb_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	/* verify that samplerate, freq and size is what we have set in
+	 * the link.
+	 */
+
+	return 0;
+}
+
+/*
+ * When the PCM stream is started, stopped, paused etc.
+ *
+ * Atomic function (some lock is being held by PCM layer)
+ */
+static int snd_avb_pcm_trigger(struct snd_pcm_substream *substream,
+			       int cmd)
+{
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		/* pr_err("%s: starting for some reason\n", __func__); */
+		tsn_lb_enable(avb_chip->link);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		/* memset buffer to 0 */
+		/* pr_err("%s: stopping for some reason\n", __func__); */
+		tsn_lb_disable(avb_chip->link);
+		break;
+	default:
+		pr_info("%s: cmd: %d (return -EINVAL)\n", __func__, cmd);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int snd_avb_get_time_info(struct snd_pcm_substream *substream,
+				struct timespec *system_ts, struct timespec *audio_ts,
+				struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
+				struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
+{
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+	struct tsn_link *link = avb_chip->link;
+	u64 nsec;
+
+	snd_pcm_gettime(substream->runtime, system_ts);
+
+	/* We only support link-time from sample, absolute (no reset) */
+	if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME) &&
+		(audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE)) {
+		tsn_lock(link);
+		nsec = link->ts_net_ns;
+		tsn_unlock(link);
+
+		*audio_ts = ns_to_timespec(nsec);
+		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE;
+
+		/* this should be accurate, but leave it as inaccurate
+		 * until we know the level for gPTP-clock in the system
+		 * accuracy_report = 1 (timestamp is accurate to within accuracy)
+		 * accuracy: in ns
+		 */
+		audio_tstamp_report->accuracy_report = 0;
+		audio_tstamp_report->accuracy = 42;
+	} else {
+		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
+	}
+
+	return 0;
+}
+
+/*
+ * current hw-position in the buffer, in frames from 0 to buffer_size -1
+ *
+ * Need to know where the hw-pointer is and how this corresponds to the
+ * underlying TSN-buffer setup
+ *
+ * Atomic function (some lock is being held by PCM layer)
+ *
+ */
+static snd_pcm_uframes_t snd_avb_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct avb_chip *avb_chip = snd_pcm_substream_chip(substream);
+	struct tsn_link *link = avb_chip->link;
+	snd_pcm_uframes_t pointer;
+
+	if (link->estype_talker)
+		pointer = bytes_to_frames(substream->runtime,
+					  link->tail - link->buffer);
+	else
+		pointer = bytes_to_frames(substream->runtime,
+					  link->head - link->buffer);
+	return pointer;
+}
+
+static struct snd_pcm_ops snd_avb_playback_ops = {
+	.open      = snd_avb_playback_open,
+	.close     = snd_avb_playback_close,
+	.copy	   = snd_avb_playback_copy,
+	.silence   = snd_avb_silence,
+	.ioctl     = snd_pcm_lib_ioctl,
+	.hw_params = snd_avb_pcm_hw_params,
+	.hw_free   = snd_avb_pcm_hw_free,
+	.prepare   = snd_avb_pcm_prepare,
+	.trigger   = snd_avb_pcm_trigger,
+	.pointer   = snd_avb_pcm_pointer,
+	.get_time_info = snd_avb_get_time_info,
+};
+
+static struct snd_pcm_ops snd_avb_capture_ops = {
+	.open      = snd_avb_capture_open,
+	.close     = snd_avb_capture_close,
+	.copy	   = snd_avb_capture_copy,
+	.silence   = snd_avb_silence,
+	.ioctl     = snd_pcm_lib_ioctl,
+	.hw_params = snd_avb_pcm_hw_params,
+	.hw_free   = snd_avb_pcm_hw_free,
+	.prepare   = snd_avb_pcm_prepare,
+	.trigger   = snd_avb_pcm_trigger,
+	.pointer   = snd_avb_pcm_pointer,
+	.get_time_info = snd_avb_get_time_info,
+};
+
+/*
+ * Callback for tsn_core for moving data into the buffer.
+ *
+ * This should be a wrapper (replace it with) the refill-functionality ALSA use.
+ */
+static size_t snd_avb_refill(struct tsn_link *link)
+{
+	struct avb_chip *avb_chip = link->media_chip;
+
+	if (avb_chip && avb_chip->substream) {
+		snd_pcm_period_elapsed(avb_chip->substream);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static size_t snd_avb_drain(struct tsn_link *link)
+{
+	struct avb_chip *avb_chip = link->media_chip;
+
+	if (avb_chip && avb_chip->substream) {
+		snd_pcm_period_elapsed(avb_chip->substream);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static size_t snd_avb_hdr_size(struct tsn_link *link)
+{
+	/* return the size of the iec61883-6 audio header */
+	return _iec61883_hdr_len();
+}
+
+static size_t snd_avb_copy_size(struct tsn_link *link)
+{
+	struct avb_chip *chip = link->media_chip;
+	/* use values in avb_chip, not link */
+	size_t framesize = (chip->sample_size >> 3) * chip->channels;
+	size_t numframes = 0;
+
+	if (!chip->sample_freq)
+		return link->max_payload_size;
+
+	/* size of each frame (samples per frame, sample-size && class)
+	 * sample_size: 16 -> 2
+	 * spframe :    12 (class b)
+	 * channels:     2
+	 *
+	 * framesize:  2*12*2 -> 48
+	 */
+
+	switch (chip->sample_freq) {
+	case 44100:
+		/*
+		 * Class B: 40 frames, first 12 bytes, next 39 should be 11
+		 */
+		if (link->class == SR_CLASS_B) {
+			numframes = (chip->num_10ms_series ? 11 : 12);
+			chip->num_10ms_series++;
+			if (chip->num_10ms_series > 39)
+				chip->num_10ms_series = 0;
+		} else {
+			/* Class A slightly more involved
+			 * Need 41 6 bytes and 39 5 bytes
+			 *
+			 * If 0th is set to 6, remaining odd idx should
+			 * be 6, even (except 0th) to be 6
+			 */
+			numframes = 5;
+			if (!chip->num_10ms_series ||
+			    (chip->num_10ms_series % 0x2))
+				numframes++;
+			chip->num_10ms_series++;
+			if (chip->num_10ms_series > 79)
+				chip->num_10ms_series = 0;
+		}
+		break;
+	case 48000:
+		numframes = (link->class == SR_CLASS_A ? 6 : 12);
+		break;
+	default:
+		pr_err("Unsupported sample_freq (%d), disabling link\n",
+		       chip->sample_freq);
+		tsn_lb_disable(link);
+		return -EINVAL;
+	}
+	return numframes * framesize;
+}
+
+static void snd_avb_assemble_iidc(struct tsn_link *link,
+				  struct avtpdu_header *header, size_t bytes)
+{
+	_iec61883_hdr_assemble(header, bytes);
+}
+
+static int snd_avb_validate_iidc(struct tsn_link *link,
+				 struct avtpdu_header *header)
+{
+	return _iec61883_hdr_verify(header);
+}
+
+static void *snd_avb_get_payload_data(struct tsn_link *link,
+				      struct avtpdu_header *header)
+{
+	return _iec61883_payload(header);
+}
+
+static int snd_avb_new_pcm(struct avb_chip *avb_chip, int device)
+{
+	struct snd_pcm *pcm;
+	int err;
+
+	err = snd_pcm_new(avb_chip->card, "AVB PCM", device, 1, 1, &pcm);
+	if (err < 0)
+		return err;
+	pcm->private_data = avb_chip;
+	strcpy(pcm->name, "AVB PCM");
+	avb_chip->pcm = pcm;
+
+	/* only playback at the moment, once we implement capture, we
+	 * need to grab the Talker/Listener from TSN link
+	 */
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_avb_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,  &snd_avb_capture_ops);
+
+	return 0;
+
+}
+
+static int snd_avb_probe(struct platform_device *devptr)
+{
+	int err;
+	struct snd_card *card;
+	struct avb_chip *avb_chip;
+	int dev = devptr->id;
+
+	pr_info("%s: starting\n", __func__);
+
+	err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+			   sizeof(struct avb_chip), &card);
+	if (err < 0) {
+		pr_err("%s: trouble creating new card -> %d\n",
+			__func__, err);
+		return err;
+	}
+	avb_chip = card->private_data;
+	avb_chip->card = card;
+
+
+	/* create PCM device*/
+	err = snd_avb_new_pcm(avb_chip, 0);
+	if (err < 0) {
+		pr_err("%s: could not create new PCM device\n", __func__);
+		goto err_out;
+	}
+
+	/* register card */
+	pr_info("%s: ready to register card\n", __func__);
+	strcpy(card->driver, "Avb");
+	strcpy(card->shortname, "Avb");
+	sprintf(card->longname, "Avb %i", devptr->id + 1);
+	err = snd_card_register(card);
+	if (err < 0) {
+		pr_err("%s: Could not register card -> %d\n",
+			__func__, err);
+		snd_card_free(card);
+		return err;
+	}
+
+	if (err == 0) {
+		platform_set_drvdata(devptr, card);
+		pr_info("%s: Successfully initialized %s\n",
+			__func__, card->shortname);
+		return 0;
+	}
+err_out:
+	snd_card_free(card);
+	return err;
+}
+
+/*
+ * We are here as a result from being removed via
+ * tsn_link->shim_ops->media_close, which is snd_avb_close()
+ */
+static int snd_avb_remove(struct platform_device *devptr)
+{
+	struct snd_card *card     = platform_get_drvdata(devptr);
+	struct avb_chip *avb_chip = card->private_data;
+
+	/* Make sure link holds no ref to this now dead card */
+	if (avb_chip && avb_chip->link) {
+		avb_chip->link->media_chip = NULL;
+		avb_chip->link = NULL;
+	}
+
+	/* call into link->ops->media_close() ? */
+	snd_card_free(card);
+	return 0;
+}
+
+static struct platform_driver snd_avb_driver = {
+	.probe  = snd_avb_probe,
+	.remove = snd_avb_remove,
+	.driver = {
+		.name = "snd_avb",
+		.pm   = NULL,	/* don't care about Power Management */
+	},
+};
+
+static int snd_avb_close(struct tsn_link *link)
+{
+	struct avb_chip *avb_chip = link->media_chip;
+
+	if (!link->media_chip)
+		return 0;
+
+	pr_info("%s: Removing device\n", __func__);
+
+	platform_device_unregister(avb_chip->device);
+	/* platform unregister will call into snd_avb_remove */
+	platform_driver_unregister(&snd_avb_driver);
+
+	/* update link to remove pointer to now invalid memory */
+	link->media_chip = NULL;
+	return 0;
+}
+
+static int snd_avb_new(struct tsn_link *link)
+{
+	struct avb_chip *avb_chip;
+	struct snd_card *card;
+	struct platform_device *device;
+	int err;
+
+	err = platform_driver_register(&snd_avb_driver);
+	if (err < 0) {
+		pr_info("%s: trouble registering driver %d, unreg. partial driver and abort.\n",
+			__func__, err);
+		return err;
+	}
+
+	/*
+	 * We only register a single card for now, look to
+	 * /sys/devices/platform/snd_avb.0 for content.
+	 *
+	 * Probe will be triggered if name is same as .name in platform_driver
+	 */
+	device = platform_device_register_simple("snd_avb", 0, NULL, 0);
+	if (IS_ERR(device)) {
+		pr_info("%s: ERROR registering simple platform-device\n",
+			__func__);
+		platform_driver_unregister(&snd_avb_driver);
+		return -ENODEV;
+	}
+
+	/* store data in driver so we can access it in .probe */
+	card = platform_get_drvdata(device);
+	if (card == NULL) {
+		pr_info("%s: Did not get anything from platform_get_drvdata()\n",
+			__func__);
+		platform_device_unregister(device);
+		return -ENODEV;
+	}
+	avb_chip = card->private_data;
+	avb_chip->device = device;
+	avb_chip->link = link;
+
+	link->media_chip = avb_chip;
+
+	return 0;
+}
+
+static struct tsn_shim_ops shim_ops = {
+	.shim_name	 = "alsa",
+	.probe		 = snd_avb_new,
+	.buffer_refill   = snd_avb_refill,
+	.buffer_drain    = snd_avb_drain,
+	.media_close     = snd_avb_close,
+	.hdr_size        = snd_avb_hdr_size,
+	.copy_size       = snd_avb_copy_size,
+	.assemble_header = snd_avb_assemble_iidc,
+	.validate_header = snd_avb_validate_iidc,
+	.get_payload_data = snd_avb_get_payload_data,
+};
+
+static int __init avb_alsa_init(void)
+{
+	if (tsn_shim_register_ops(&shim_ops)) {
+		pr_err("Could not register ALSA-shim with TSN\n");
+		return -EINVAL;
+	}
+	pr_info("AVB ALSA added OK\n");
+	return 0;
+}
+
+static void __exit avb_alsa_exit(void)
+{
+	tsn_shim_deregister_ops(&shim_ops);
+}
+
+module_init(avb_alsa_init);
+module_exit(avb_alsa_exit);
+MODULE_AUTHOR("Henrik Austad");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TSN ALSA shim driver");
diff --git a/drivers/media/avb/tsn_iec61883.h b/drivers/media/avb/tsn_iec61883.h
new file mode 100644
index 0000000..167bfd8
--- /dev/null
+++ b/drivers/media/avb/tsn_iec61883.h
@@ -0,0 +1,152 @@
+#ifndef TSN_IEC61883_H
+#define TSN_IEC61883_H
+#include <linux/tsn.h>
+
+/*
+ * psh:
+ *  tag:2
+ *  channel:6
+ *  tcode:4
+ *  sy:4
+ * See IEEE 1722.1 :: 6.2 for details
+ */
+struct iec61883_tag {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	u8 tag:2;
+	u8 channel:6;
+	u8 tcode:4;
+	u8 sy:4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+	u8 channel:6;
+	u8 tag:2;
+	u8 sy:4;
+	u8 sy:4;
+#else
+#error "Unknown Endianness, cannot determine bitfield ordering"
+#endif
+} __packed;
+
+struct iec61883_audio_header {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	u8 sid:6;
+	u8 cip_1:2;
+
+	u8 dbs:8;
+
+	u8 rsv:2;		/* reserved */
+	u8 sph:1;
+	u8 qpc:3;
+	u8 fn:2;
+
+	u8 dbc;
+
+	u8 fmt:6;
+	u8 cip_2:2;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+	u8 cip_1:2;
+	u8 sid:6;
+
+	u8 dbs:8;
+
+	u8 fn:2;
+	u8 qpc:3;
+	u8 sph:1;
+	u8 rsv:2;		/* reserved */
+
+	u8 dbc;
+
+	u8 cip_2:2;
+	u8 fmt:6;
+#else
+#error "Unknown Endianness, cannot determine bitfield ordering"
+#endif
+	u8 fdf;
+	u16 syt;
+	u8 payload[0];
+} __packed;
+
+static inline size_t _iec61883_hdr_len(void)
+{
+	return sizeof(struct iec61883_audio_header);
+}
+
+static inline int _iec61883_hdr_verify(struct avtpdu_header *hdr)
+{
+	struct iec61883_audio_header *dh;
+	struct iec61883_tag *psh;
+
+	if (hdr->subtype != TSN_61883_IIDC)
+		return -EINVAL;
+	dh  = (struct iec61883_audio_header *)&hdr->data;
+	psh = (struct iec61883_tag *)&hdr->psh;
+
+	/* Verify 61883 header */
+	if (psh->tag != 1 || psh->channel != 31 ||
+		psh->tcode != 0xA || psh->sy != 0)
+		return -EINVAL;
+
+	/* check flags that should be static from frame to frame */
+	if (dh->cip_1 != 0 || dh->sid != 0x3f || dh->qpc != 0 || dh->fn != 0 ||
+		dh->sph != 0 || dh->cip_2 != 2)
+		return -EINVAL;
+
+	if (dh->dbs != ntohs(hdr->sd_len)*2 || dh->dbc != hdr->seqnr)
+		return -EINVAL;
+
+	return 0;
+}
+
+static inline void _iec61883_hdr_assemble(struct avtpdu_header *hdr,
+					  size_t bytes)
+{
+	struct iec61883_tag *psh;
+	struct iec61883_audio_header *dh;
+
+	if (bytes > 0x7f)
+		pr_warn("%s: hdr->dbs will overflow, malformed frame will be the result\n",
+			__func__);
+
+
+	hdr->subtype = TSN_61883_IIDC;
+
+	/* IIDC 61883 header */
+	psh = (struct iec61883_tag *)&hdr->psh;
+	psh->tag = 1;
+	psh->channel = 31;      /* 0x1f */
+	psh->tcode = 0xA;
+	psh->sy = 0;
+
+	dh = (struct iec61883_audio_header *)&hdr->data;
+	dh->cip_1 = 0;
+	dh->sid = 63;           /* 0x3f */
+	dh->dbs = (u8)(bytes*2); /* number of quadlets of data in AVTPDU */
+	dh->qpc = 0;
+	dh->fn = 0;
+	dh->sph = 0;
+	dh->dbc = hdr->seqnr;
+	dh->cip_2 = 2;
+
+	/*
+	 * FMT (Format ID): same as specified in iec 61883-1:2003
+	 *
+	 * For IEC 61883-6, it shall be 0x10 (16) to define Audio and
+	 * Music data
+	 */
+	dh->fmt = 0x10;
+
+	/* FIXME: find value
+	 * Could be sampling-freq, but 8 bits give 0 - 65kHz sampling.
+	 */
+	dh->fdf = 0;
+
+	dh->syt = 0xFFFF;
+}
+
+static inline void *_iec61883_payload(struct avtpdu_header *hdr)
+{
+	struct iec61883_audio_header *dh = (struct iec61883_audio_header *)&hdr->data;
+	/* TODO: add some basic checks before returning payload ? */
+	return &dh->payload;
+}
+
+#endif	/* TSN_IEC61883_H */
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox