From patchwork Mon Jan 11 15:56:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ming Lei X-Patchwork-Id: 566015 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id A1E361402C9 for ; Tue, 12 Jan 2016 02:59:55 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=WE9DEEvo; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932687AbcAKP7g (ORCPT ); Mon, 11 Jan 2016 10:59:36 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:34978 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933617AbcAKP52 (ORCPT ); Mon, 11 Jan 2016 10:57:28 -0500 Received: by mail-pf0-f196.google.com with SMTP id 65so3744943pff.2; Mon, 11 Jan 2016 07:57:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Kv+j8kMmEhGsjkaTZgAahYh9e8tKw/0g9FSZcnNgIwA=; b=WE9DEEvoG+OCWdl9V8XxDETopb9zxw7pe8cAViUmlzi6kHeUwUmtlTbnfIfUv6CCNx NBIcBRr6S4V2d48HVcZ9JOQYrZZPiixrd9nxfD8F9qoIOk6bDQmrf+PPrCDtK81Ip7Gj 6Cez/7jIoDi4gDdMzBYN+Mw9JgslOx+RdmvacmYA3CczFdo3Zs5XeGVTmEBY2yvXbDHU H8cvMd1K82tB7M8cpsnmaBn4Q+z2c2Kx5hEcrWRAA0HtjNNC1FFnL6sjQjQ+OqXfqO25 znChLILqgr2RegOdLVJ2npqOu+kwPdOZ0akP2mMynelQFj6b+XExxAbL6ZnDC/6NTGX9 xXWw== X-Received: by 10.98.75.139 with SMTP id d11mr27052066pfj.57.1452527848154; Mon, 11 Jan 2016 07:57:28 -0800 (PST) Received: from localhost ([103.192.227.7]) by smtp.gmail.com with ESMTPSA id fl9sm186732427pab.33.2016.01.11.07.57.26 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 11 Jan 2016 07:57:27 -0800 (PST) From: Ming Lei To: linux-kernel@vger.kernel.org, Alexei Starovoitov Cc: "David S. Miller" , netdev@vger.kernel.org, Daniel Borkmann , Martin KaFai Lau , Ming Lei Subject: [PATCH 4/9] bpf: add percpu version of lookup/update element helpers Date: Mon, 11 Jan 2016 23:56:56 +0800 Message-Id: <1452527821-12276-5-git-send-email-tom.leiming@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1452527821-12276-1-git-send-email-tom.leiming@gmail.com> References: <1452527821-12276-1-git-send-email-tom.leiming@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Prepare for supporting percpu map. These introduced two callback & helpers can be used to retrieve/update the value from one specific CPU for percpu map. Signed-off-by: Ming Lei --- include/linux/bpf.h | 3 +++ include/uapi/linux/bpf.h | 6 ++++++ kernel/bpf/core.c | 2 ++ kernel/bpf/helpers.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ net/core/filter.c | 4 ++++ 5 files changed, 68 insertions(+) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 7fa339f..75d75d8 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -219,6 +219,9 @@ extern const struct bpf_func_proto bpf_get_current_comm_proto; extern const struct bpf_func_proto bpf_skb_vlan_push_proto; extern const struct bpf_func_proto bpf_skb_vlan_pop_proto; +extern const struct bpf_func_proto bpf_map_lookup_elem_percpu_proto; +extern const struct bpf_func_proto bpf_map_update_elem_percpu_proto; + /* Shared helpers among cBPF and eBPF. */ void bpf_user_rnd_init_once(void); u64 bpf_user_rnd_u32(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 8bed7f1..2658917 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -270,6 +270,12 @@ enum bpf_func_id { */ BPF_FUNC_perf_event_output, BPF_FUNC_skb_load_bytes, + + /* void *map_lookup_elem(&map, &key, cpu) */ + BPF_FUNC_map_lookup_elem_percpu, + /* int map_update_elem(&map, &key, &value, flags, cpu) */ + BPF_FUNC_map_update_elem_percpu, + __BPF_FUNC_MAX_ID, }; diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 972d9a8..71a09fa 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -769,6 +769,8 @@ const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void) { return NULL; } +const struct bpf_func_proto bpf_map_lookup_elem_percpu_proto __weak; +const struct bpf_func_proto bpf_map_update_elem_percpu_proto __weak; /* Always built-in helper functions. */ const struct bpf_func_proto bpf_tail_call_proto = { diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 4504ca6..d05164a 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -54,6 +54,36 @@ const struct bpf_func_proto bpf_map_lookup_elem_proto = { .arg2_type = ARG_PTR_TO_MAP_KEY, }; +static u64 bpf_map_lookup_elem_percpu(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) +{ + /* verifier checked that R1 contains a valid pointer to bpf_map + * and R2 points to a program stack and map->key_size bytes were + * initialized + */ + struct bpf_map *map = (struct bpf_map *) (unsigned long) r1; + void *key = (void *) (unsigned long) r2; + u32 cpu = (u32)(unsigned long) r3; + void *value; + + WARN_ON_ONCE(!rcu_read_lock_held()); + + value = map->ops->map_lookup_elem_percpu(map, key, cpu); + + /* lookup() returns either pointer to element value or NULL + * which is the meaning of PTR_TO_MAP_VALUE_OR_NULL type + */ + return (unsigned long) value; +} + +const struct bpf_func_proto bpf_map_lookup_elem_percpu_proto = { + .func = bpf_map_lookup_elem_percpu, + .gpl_only = false, + .ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL, + .arg1_type = ARG_CONST_MAP_PTR, + .arg2_type = ARG_PTR_TO_MAP_KEY, + .arg3_type = ARG_ANYTHING, +}; + static u64 bpf_map_update_elem(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) { struct bpf_map *map = (struct bpf_map *) (unsigned long) r1; @@ -75,6 +105,29 @@ const struct bpf_func_proto bpf_map_update_elem_proto = { .arg4_type = ARG_ANYTHING, }; +static u64 bpf_map_update_elem_percpu(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) +{ + struct bpf_map *map = (struct bpf_map *) (unsigned long) r1; + void *key = (void *) (unsigned long) r2; + void *value = (void *) (unsigned long) r3; + u32 cpu = (u32)(unsigned long) r5; + + WARN_ON_ONCE(!rcu_read_lock_held()); + + return map->ops->map_update_elem_percpu(map, key, value, r4, cpu); +} + +const struct bpf_func_proto bpf_map_update_elem_percpu_proto = { + .func = bpf_map_update_elem_percpu, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_CONST_MAP_PTR, + .arg2_type = ARG_PTR_TO_MAP_KEY, + .arg3_type = ARG_PTR_TO_MAP_VALUE, + .arg4_type = ARG_ANYTHING, + .arg5_type = ARG_ANYTHING, +}; + static u64 bpf_map_delete_elem(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) { struct bpf_map *map = (struct bpf_map *) (unsigned long) r1; diff --git a/net/core/filter.c b/net/core/filter.c index 35e6fed..8c558fc 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -1743,8 +1743,12 @@ sk_filter_func_proto(enum bpf_func_id func_id) switch (func_id) { case BPF_FUNC_map_lookup_elem: return &bpf_map_lookup_elem_proto; + case BPF_FUNC_map_lookup_elem_percpu: + return &bpf_map_lookup_elem_percpu_proto; case BPF_FUNC_map_update_elem: return &bpf_map_update_elem_proto; + case BPF_FUNC_map_update_elem_percpu: + return &bpf_map_update_elem_percpu_proto; case BPF_FUNC_map_delete_elem: return &bpf_map_delete_elem_proto; case BPF_FUNC_get_prandom_u32: