From patchwork Wed Oct 2 13:30:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 1170658 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46jxpc1fBrz9sPq for ; Wed, 2 Oct 2019 23:30:32 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727888AbfJBNab (ORCPT ); Wed, 2 Oct 2019 09:30:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39858 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727869AbfJBNaa (ORCPT ); Wed, 2 Oct 2019 09:30:30 -0400 Received: from mail-lj1-f200.google.com (mail-lj1-f200.google.com [209.85.208.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A3C868763B for ; Wed, 2 Oct 2019 13:30:29 +0000 (UTC) Received: by mail-lj1-f200.google.com with SMTP id l13so4865684lji.7 for ; Wed, 02 Oct 2019 06:30:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=zxVp0oQW9P1sFKHaI9R9o1AFUMKzBOp7SdYP5JimPZo=; b=O92C3MYDkJ9yxM4UlO6buWBZfTtTvEBwB+x9ckLUGccMDrwDy4dVYMVIO8nbOsl4MD UGZI49+F83WPEylgNyMSKjyaonP21dCdRv8//P/b+oVmk1vHamcA8i7KjUf4r05WogMN Os9BGmXIHuOjfjTJxowK2fGG2XzuFeG5GyXdAy6baW1Hw9sjQlx87mmfr0C/laFbyzUH +ty0xgVXwTX4B/W5jXKnh9DUXAkyaAEL/vUAf5JJFNLZdcfpOb7ciAR5gIWWChRIij/j Clr/1kupS5IjaW5UxbpHUZziVBe+V/LZbwNRngui8OLvNfyZ9Wuc+Ryf5DlFK0BBYPp9 XMKQ== X-Gm-Message-State: APjAAAUih/CPO+g6ATW8q+4+BSthV7UyVz3N4Tviwke31xiLUCeI9eq+ A3wJEU+S/ZYFeFsKseslrIYRZy9rC6NTpILFvzM0auFIvaWbrq8fItEkk91sM5rgz6qldi0T98X 1tl/pLkcBK3ajtWd/ X-Received: by 2002:a2e:7010:: with SMTP id l16mr2531612ljc.30.1570023027364; Wed, 02 Oct 2019 06:30:27 -0700 (PDT) X-Google-Smtp-Source: APXvYqxEYmgbkp2r9lxcYPcJPq1Rm82i91/W2uU9/3M8voFck9WzQxTtYO4FjuRGn4ap9COXrQn2xA== X-Received: by 2002:a2e:7010:: with SMTP id l16mr2531601ljc.30.1570023027166; Wed, 02 Oct 2019 06:30:27 -0700 (PDT) Received: from alrua-x1.borgediget.toke.dk ([2a00:7660:6da:443::2]) by smtp.gmail.com with ESMTPSA id 202sm4772280ljf.75.2019.10.02.06.30.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2019 06:30:26 -0700 (PDT) Received: by alrua-x1.borgediget.toke.dk (Postfix, from userid 1000) id B0BBD180640; Wed, 2 Oct 2019 15:30:25 +0200 (CEST) Subject: [PATCH bpf-next 1/9] hashtab: Add new bpf_map_fd_put_value op From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: Daniel Borkmann Cc: Alexei Starovoitov , Martin KaFai Lau , Song Liu , Yonghong Song , Marek Majkowski , Lorenz Bauer , David Miller , Jesper Dangaard Brouer , netdev@vger.kernel.org, bpf@vger.kernel.org Date: Wed, 02 Oct 2019 15:30:25 +0200 Message-ID: <157002302565.1302756.3212597038181844705.stgit@alrua-x1> In-Reply-To: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> References: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Toke Høiland-Jørgensen The fd type maps all resolve the fd into a pointer to the underlying object when it is inserted into the map, and stores that pointer as the real array value. The htab code assumes that the map value is this single pointer, and dereferences it before passing it to the map fd_put_ptr() op. For xdp chain maps we want to be able to store multiple pointers, so we need to get the pointer to the map value store, not the dereferenced pointer to the actual object. So add a new more general bpf_map_fd_put_value() op that takes the map value instead of the dereferenced pointer, and use this on map element free. Signed-off-by: Toke Høiland-Jørgensen --- include/linux/bpf.h | 1 + kernel/bpf/hashtab.c | 16 ++++++---------- kernel/bpf/map_in_map.c | 7 +++++++ kernel/bpf/map_in_map.h | 1 + 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 5b9d22338606..be3e9e9109c7 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -50,6 +50,7 @@ struct bpf_map_ops { void *(*map_fd_get_ptr)(struct bpf_map *map, struct file *map_file, int fd); void (*map_fd_put_ptr)(void *ptr); + void (*map_fd_put_value)(void *value); u32 (*map_gen_lookup)(struct bpf_map *map, struct bpf_insn *insn_buf); u32 (*map_fd_sys_lookup_elem)(void *ptr); void (*map_seq_show_elem)(struct bpf_map *map, void *key, diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 22066a62c8c9..113e1286e184 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -87,11 +87,6 @@ static inline void __percpu *htab_elem_get_ptr(struct htab_elem *l, u32 key_size return *(void __percpu **)(l->key + key_size); } -static void *fd_htab_map_get_ptr(const struct bpf_map *map, struct htab_elem *l) -{ - return *(void **)(l->key + roundup(map->key_size, 8)); -} - static struct htab_elem *get_htab_elem(struct bpf_htab *htab, int i) { return (struct htab_elem *) (htab->elems + i * htab->elem_size); @@ -679,10 +674,10 @@ static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l) { struct bpf_map *map = &htab->map; - if (map->ops->map_fd_put_ptr) { - void *ptr = fd_htab_map_get_ptr(map, l); + if (map->ops->map_fd_put_value) { + void *value = l->key + round_up(map->key_size, 8); - map->ops->map_fd_put_ptr(ptr); + map->ops->map_fd_put_value(value); } if (htab_is_prealloc(htab)) { @@ -1400,9 +1395,9 @@ static void fd_htab_map_free(struct bpf_map *map) head = select_bucket(htab, i); hlist_nulls_for_each_entry_safe(l, n, head, hash_node) { - void *ptr = fd_htab_map_get_ptr(map, l); + void *value = l->key + round_up(map->key_size, 8); - map->ops->map_fd_put_ptr(ptr); + map->ops->map_fd_put_value(value); } } @@ -1510,6 +1505,7 @@ const struct bpf_map_ops htab_of_maps_map_ops = { .map_delete_elem = htab_map_delete_elem, .map_fd_get_ptr = bpf_map_fd_get_ptr, .map_fd_put_ptr = bpf_map_fd_put_ptr, + .map_fd_put_value = bpf_map_fd_put_value, .map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem, .map_gen_lookup = htab_of_map_gen_lookup, .map_check_btf = map_check_no_btf, diff --git a/kernel/bpf/map_in_map.c b/kernel/bpf/map_in_map.c index fab4fb134547..1b4e8b6da777 100644 --- a/kernel/bpf/map_in_map.c +++ b/kernel/bpf/map_in_map.c @@ -114,6 +114,13 @@ void bpf_map_fd_put_ptr(void *ptr) bpf_map_put(ptr); } +void bpf_map_fd_put_value(void *value) +{ + void **ptr = value; + + bpf_map_fd_put_ptr(*ptr); +} + u32 bpf_map_fd_sys_lookup_elem(void *ptr) { return ((struct bpf_map *)ptr)->id; diff --git a/kernel/bpf/map_in_map.h b/kernel/bpf/map_in_map.h index a507bf6ef8b9..68d1a52e1757 100644 --- a/kernel/bpf/map_in_map.h +++ b/kernel/bpf/map_in_map.h @@ -16,6 +16,7 @@ bool bpf_map_meta_equal(const struct bpf_map *meta0, void *bpf_map_fd_get_ptr(struct bpf_map *map, struct file *map_file, int ufd); void bpf_map_fd_put_ptr(void *ptr); +void bpf_map_fd_put_value(void *value); u32 bpf_map_fd_sys_lookup_elem(void *ptr); #endif From patchwork Wed Oct 2 13:30:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 1170672 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46jxps6nPQz9sDB for ; Wed, 2 Oct 2019 23:30:45 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727963AbfJBNaf (ORCPT ); Wed, 2 Oct 2019 09:30:35 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54684 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727933AbfJBNad (ORCPT ); Wed, 2 Oct 2019 09:30:33 -0400 Received: from mail-lj1-f197.google.com (mail-lj1-f197.google.com [209.85.208.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EA40281127 for ; Wed, 2 Oct 2019 13:30:32 +0000 (UTC) Received: by mail-lj1-f197.google.com with SMTP id b90so4859758ljf.11 for ; Wed, 02 Oct 2019 06:30:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=1Wsj/lXR0FWl5TJU2feRxQ1sy5OmHjYGRJ/DyODED4I=; b=EF8MWAF5vpEOPYtqxDgGLFMnklmZL/HawVUPY5aAumgb/AzLIfsCD2DqoOHI25tro4 OBNYVD+x/LVQMXldcalSySrAoORehv+4CyeHaEc56fDI75AGySMPoYhhA64IrZkS4s8D vAA1y4oe5t/+encT2UNbrN3LL2dhsQubVAv0aNjUCGRCym3J7ugPbmZqj63eJWCFkhTE ZCH9uESiYIjS4Fc7Q2nPtLSfdYA7rzS4K3SIIb0ZKlPWntPwUsMeryH/vB2RgJP8JO9H uhHsVXwPoUpadBFve4t/h6R53RzXpx2M4HTqui9DU++XAA39WepLTont/U052tbI2wiQ NeHQ== X-Gm-Message-State: APjAAAWOoVdsAFUl2PX6xxRoF7ccN+n313JVb8DJPM3QcJXUFXBmUFnZ 41NDsERLJDfnfu4XSR150InXf0OMDNZsE6TYNXE39NQzz5yAcxk62W2B6NwCthcP8ZDen8JlJSt uCMtDB4c8BG2nZSYZ X-Received: by 2002:a2e:b009:: with SMTP id y9mr2473334ljk.185.1570023031346; Wed, 02 Oct 2019 06:30:31 -0700 (PDT) X-Google-Smtp-Source: APXvYqzxpvV1HU+8j/DE1KIvlQwjx6aFy5Y3VD//w5fRCydHkdEsxNoSEY/t/ptTvvccOhDhuMZ+sQ== X-Received: by 2002:a2e:b009:: with SMTP id y9mr2473304ljk.185.1570023031046; Wed, 02 Oct 2019 06:30:31 -0700 (PDT) Received: from alrua-x1.borgediget.toke.dk ([2a00:7660:6da:443::2]) by smtp.gmail.com with ESMTPSA id l3sm4668906lfc.31.2019.10.02.06.30.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2019 06:30:29 -0700 (PDT) Received: by alrua-x1.borgediget.toke.dk (Postfix, from userid 1000) id CE0CD18063D; Wed, 2 Oct 2019 15:30:26 +0200 (CEST) Subject: [PATCH bpf-next 2/9] xdp: Add new xdp_chain_map type for specifying XDP call sequences From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: Daniel Borkmann Cc: Alexei Starovoitov , Martin KaFai Lau , Song Liu , Yonghong Song , Marek Majkowski , Lorenz Bauer , David Miller , Jesper Dangaard Brouer , netdev@vger.kernel.org, bpf@vger.kernel.org Date: Wed, 02 Oct 2019 15:30:26 +0200 Message-ID: <157002302672.1302756.10579143571088111093.stgit@alrua-x1> In-Reply-To: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> References: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Toke Høiland-Jørgensen To specify call sequences for XDP programs, we need to do a lookup after an XDP program runs to get the next program to run. Introduce a new map type for this use which allows specifying one action per return code of the original program. The new map type is derived from the hashmap type, and uses the program ID as the lookup key. The value is a struct of program pointers specifying the next program in the call sequence for each return code of the previous program. A special wildcard pointer can also be specified which will match on all program return codes if no more specific entry is included in the structure (i.e., LPM-style matching). Userspace fills in a struct of program fds and passes that as the value, and the map converts the fds to pointers before inserting the structure into the map. Using the map type directly from an eBPF program is disallowed; instead, a subsequent commit will add lookup code to the XDP dispatch function, and the ability for userspace to set the current chain call map when attaching an XDP program to an interface. Signed-off-by: Toke Høiland-Jørgensen --- include/linux/bpf.h | 9 +++ include/linux/bpf_types.h | 1 include/uapi/linux/bpf.h | 12 ++++ kernel/bpf/hashtab.c | 153 +++++++++++++++++++++++++++++++++++++++++++++ kernel/bpf/syscall.c | 11 +++ 5 files changed, 186 insertions(+) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index be3e9e9109c7..e72702c4cb12 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -689,6 +689,15 @@ int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file, void *key, void *value, u64 map_flags); int bpf_fd_htab_map_lookup_elem(struct bpf_map *map, void *key, u32 *value); +int bpf_xdp_chain_map_update_elem(struct bpf_map *map, void *key, void *value, + u64 map_flags); +int bpf_xdp_chain_map_lookup_elem(struct bpf_map *map, void *key, void *value); +struct bpf_prog *bpf_xdp_chain_map_get_prog(struct bpf_map *map, + u32 prev_id, + enum xdp_action action); + + + int bpf_get_file_flag(int flags); int bpf_check_uarg_tail_zero(void __user *uaddr, size_t expected_size, size_t actual_size); diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h index 36a9c2325176..95650ed86a12 100644 --- a/include/linux/bpf_types.h +++ b/include/linux/bpf_types.h @@ -63,6 +63,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_HASH_OF_MAPS, htab_of_maps_map_ops) #ifdef CONFIG_NET BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP, dev_map_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP_HASH, dev_map_hash_ops) +BPF_MAP_TYPE(BPF_MAP_TYPE_XDP_CHAIN, xdp_chain_map_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_SK_STORAGE, sk_storage_map_ops) #if defined(CONFIG_BPF_STREAM_PARSER) BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 77c6be96d676..8b336fb68880 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -136,6 +136,7 @@ enum bpf_map_type { BPF_MAP_TYPE_STACK, BPF_MAP_TYPE_SK_STORAGE, BPF_MAP_TYPE_DEVMAP_HASH, + BPF_MAP_TYPE_XDP_CHAIN, }; /* Note that tracing related programs such as @@ -3153,6 +3154,17 @@ enum xdp_action { XDP_PASS, XDP_TX, XDP_REDIRECT, + + __XDP_ACT_MAX /* leave at end */ +}; +#define XDP_ACT_MAX (__XDP_ACT_MAX - 1) + +struct xdp_chain_acts { + __u32 wildcard_act; + __u32 drop_act; + __u32 pass_act; + __u32 tx_act; + __u32 redirect_act; }; /* user accessible metadata for XDP packet hook diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 113e1286e184..ab855095c830 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -1510,3 +1510,156 @@ const struct bpf_map_ops htab_of_maps_map_ops = { .map_gen_lookup = htab_of_map_gen_lookup, .map_check_btf = map_check_no_btf, }; + +struct xdp_chain_table { + struct bpf_prog *wildcard_act; + struct bpf_prog *act[XDP_ACT_MAX]; +}; + +static int xdp_chain_map_alloc_check(union bpf_attr *attr) +{ + BUILD_BUG_ON(sizeof(struct xdp_chain_table) / sizeof(void *) != + sizeof(struct xdp_chain_acts) / sizeof(u32)); + + if (attr->key_size != sizeof(u32) || + attr->value_size != sizeof(struct xdp_chain_acts)) + return -EINVAL; + + attr->value_size = sizeof(struct xdp_chain_table); + return htab_map_alloc_check(attr); +} + +struct bpf_prog *bpf_xdp_chain_map_get_prog(struct bpf_map *map, + u32 prev_id, + enum xdp_action action) +{ + struct xdp_chain_table *tab; + void *ptr; + + ptr = htab_map_lookup_elem(map, &prev_id); + + if (!ptr) + return NULL; + + tab = READ_ONCE(ptr); + return tab->act[action - 1] ?: tab->wildcard_act; +} +EXPORT_SYMBOL_GPL(bpf_xdp_chain_map_get_prog); + +/* only called from syscall */ +int bpf_xdp_chain_map_lookup_elem(struct bpf_map *map, void *key, void *value) +{ + struct xdp_chain_acts *act = value; + struct xdp_chain_table *tab; + void *ptr; + u32 *cur; + int i; + + ptr = htab_map_lookup_elem(map, key); + if (!ptr) + return -ENOENT; + + tab = READ_ONCE(ptr); + + if (tab->wildcard_act) + act->wildcard_act = tab->wildcard_act->aux->id; + + cur = &act->drop_act; + for (i = 0; i < XDP_ACT_MAX; i++, cur++) + if(tab->act[i]) + *cur = tab->act[i]->aux->id; + + return 0; +} + +static void *xdp_chain_map_get_ptr(int fd) +{ + struct bpf_prog *prog = bpf_prog_get(fd); + + if (IS_ERR(prog)) + return prog; + + if (prog->type != BPF_PROG_TYPE_XDP || + bpf_prog_is_dev_bound(prog->aux)) { + bpf_prog_put(prog); + return ERR_PTR(-EINVAL); + } + + return prog; +} + +static void xdp_chain_map_put_ptrs(void *value) +{ + struct xdp_chain_table *tab = value; + int i; + + for (i = 0; i < XDP_ACT_MAX; i++) + if (tab->act[i]) + bpf_prog_put(tab->act[i]); + + if (tab->wildcard_act) + bpf_prog_put(tab->wildcard_act); +} + +/* only called from syscall */ +int bpf_xdp_chain_map_update_elem(struct bpf_map *map, void *key, void *value, + u64 map_flags) +{ + struct xdp_chain_acts *act = value; + struct xdp_chain_table tab = {}; + u32 lookup_key = *((u32*)key); + u32 *cur = &act->drop_act; + bool found_val = false; + int ret, i; + void *ptr; + + if (!lookup_key) + return -EINVAL; + + if (act->wildcard_act) { + ptr = xdp_chain_map_get_ptr(act->wildcard_act); + if (IS_ERR(ptr)) + return PTR_ERR(ptr); + tab.wildcard_act = ptr; + found_val = true; + } + + for (i = 0; i < XDP_ACT_MAX; i++, cur++) { + if (*cur) { + ptr = xdp_chain_map_get_ptr(*cur); + if (IS_ERR(ptr)) { + ret = PTR_ERR(ptr); + goto out_err; + } + tab.act[i] = ptr; + found_val = true; + } + } + + if (!found_val) { + ret = -EINVAL; + goto out_err; + } + + ret = htab_map_update_elem(map, key, &tab, map_flags); + if (ret) + goto out_err; + + return ret; + +out_err: + xdp_chain_map_put_ptrs(&tab); + + return ret; +} + + +const struct bpf_map_ops xdp_chain_map_ops = { + .map_alloc_check = xdp_chain_map_alloc_check, + .map_alloc = htab_map_alloc, + .map_free = fd_htab_map_free, + .map_get_next_key = htab_map_get_next_key, + .map_delete_elem = htab_map_delete_elem, + .map_fd_put_value = xdp_chain_map_put_ptrs, + .map_check_btf = map_check_no_btf, +}; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 82eabd4e38ad..c9afaace048d 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -778,6 +778,8 @@ static int map_lookup_elem(union bpf_attr *attr) value_size = round_up(map->value_size, 8) * num_possible_cpus(); else if (IS_FD_MAP(map)) value_size = sizeof(u32); + else if (map->map_type == BPF_MAP_TYPE_XDP_CHAIN) + value_size = sizeof(struct xdp_chain_acts); else value_size = map->value_size; @@ -806,6 +808,8 @@ static int map_lookup_elem(union bpf_attr *attr) err = bpf_fd_array_map_lookup_elem(map, key, value); } else if (IS_FD_HASH(map)) { err = bpf_fd_htab_map_lookup_elem(map, key, value); + } else if (map->map_type == BPF_MAP_TYPE_XDP_CHAIN) { + err = bpf_xdp_chain_map_lookup_elem(map, key, value); } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) { err = bpf_fd_reuseport_array_lookup_elem(map, key, value); } else if (map->map_type == BPF_MAP_TYPE_QUEUE || @@ -908,6 +912,8 @@ static int map_update_elem(union bpf_attr *attr) map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY || map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) value_size = round_up(map->value_size, 8) * num_possible_cpus(); + else if (map->map_type == BPF_MAP_TYPE_XDP_CHAIN) + value_size = sizeof(struct xdp_chain_acts); else value_size = map->value_size; @@ -954,6 +960,11 @@ static int map_update_elem(union bpf_attr *attr) err = bpf_fd_htab_map_update_elem(map, f.file, key, value, attr->flags); rcu_read_unlock(); + } else if (map->map_type == BPF_MAP_TYPE_XDP_CHAIN) { + rcu_read_lock(); + err = bpf_xdp_chain_map_update_elem(map, key, value, + attr->flags); + rcu_read_unlock(); } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) { /* rcu_read_lock() is not needed */ err = bpf_fd_reuseport_array_update_elem(map, key, value, From patchwork Wed Oct 2 13:30:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 1170666 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46jxpn4nnjz9sPq for ; Wed, 2 Oct 2019 23:30:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727976AbfJBNag (ORCPT ); Wed, 2 Oct 2019 09:30:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36750 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727961AbfJBNaf (ORCPT ); Wed, 2 Oct 2019 09:30:35 -0400 Received: from mail-lj1-f198.google.com (mail-lj1-f198.google.com [209.85.208.198]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id ACD12C049D59 for ; Wed, 2 Oct 2019 13:30:34 +0000 (UTC) Received: by mail-lj1-f198.google.com with SMTP id 205so4852930ljf.13 for ; Wed, 02 Oct 2019 06:30:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=MbRvjz+ayvhsM9IuG/jm9f41EnIQ3Vg+fezDs5aB4Tc=; b=kfg97c/hsajE+7fVjr5thCosgICS7IDP4TmAtis3e/IgmoDhC3D+2OyJBzwVSzWKpO gMiXio0PMpAVR00+Wj8FE6JzA0Gh79isMU8rcrE3PA9T3gEUfdpYf68XbTM4NvMgArai jbFkx40cHQ+50B9tAxSrIIa5bOqgg+fy9mGL0JtU9rDFfNuOFb7/9EjLmFql8DEGrz15 UCEuzE2ky8d4NCp5HU4RDMyeJhjJrk7uaWy9zlBl8zwpztN7mTAxaDaNwytk6qWyGSq/ KQVppwo9RXbHDSXguqdr6MoS6wkHUF3WmkyhC0Lu5rEhBmsTcMXVbVQ5uEFr8MRI3OyQ lmzA== X-Gm-Message-State: APjAAAWc3WIwJ13mTyarUP64kY3LZSGavQ06e3nXB7W+HaayG7LuiviI 79Pm95uKquX1UKeemgEk7g5/zS6TtToI1yI4ZSjBWPRLdmLJhjhQYfhq04e4goAXjBQ1JNC4G6w V9zdi5PcLdx2T X-Received: by 2002:a2e:9049:: with SMTP id n9mr2265455ljg.45.1570023033164; Wed, 02 Oct 2019 06:30:33 -0700 (PDT) X-Google-Smtp-Source: APXvYqzhItDCSb7i8ynjfpi0BvSstWb51xyb3Rm9KKA3hObciBcFvKthQDh/jZ9n5jJ2l1fAb+QWGQ== X-Received: by 2002:a2e:9049:: with SMTP id n9mr2265439ljg.45.1570023032936; Wed, 02 Oct 2019 06:30:32 -0700 (PDT) Received: from alrua-x1.borgediget.toke.dk ([2a00:7660:6da:443::2]) by smtp.gmail.com with ESMTPSA id x2sm4887334ljj.94.2019.10.02.06.30.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2019 06:30:31 -0700 (PDT) Received: by alrua-x1.borgediget.toke.dk (Postfix, from userid 1000) id E513D180640; Wed, 2 Oct 2019 15:30:27 +0200 (CEST) Subject: [PATCH bpf-next 3/9] xdp: Support setting and getting device chain map From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: Daniel Borkmann Cc: Alexei Starovoitov , Martin KaFai Lau , Song Liu , Yonghong Song , Marek Majkowski , Lorenz Bauer , David Miller , Jesper Dangaard Brouer , netdev@vger.kernel.org, bpf@vger.kernel.org Date: Wed, 02 Oct 2019 15:30:27 +0200 Message-ID: <157002302784.1302756.2073486805381846919.stgit@alrua-x1> In-Reply-To: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> References: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org From: Toke Høiland-Jørgensen This adds support to rtnetlink for setting and getting the per-device XDP chain map. The map is set by means of a new netlink attribute that contains a pointer to a BPF map of the XDP chain type. If such an attribute is included, it will be inserted into the struct net_device so that the XDP chain call code will pick it up on program execution. To prevent old userspace programs that do not understand the chain map attribute from messing up the chain call order, a netlink message with no chain map attribute set will be rejected if a chain map has already been installed. When installing a new chain call map, an XDP program fd must also be provided, otherwise the operation will be rejected. Signed-off-by: Toke Høiland-Jørgensen --- include/linux/netdevice.h | 3 ++- include/uapi/linux/if_link.h | 2 ++ net/core/dev.c | 42 ++++++++++++++++++++++++++++++++++++------ net/core/rtnetlink.c | 23 +++++++++++++++++++++++ 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 48cc71aae466..60f3b510b175 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1941,6 +1941,7 @@ struct net_device { unsigned int real_num_rx_queues; struct bpf_prog __rcu *xdp_prog; + struct bpf_map __rcu *xdp_chain_map; unsigned long gro_flush_timeout; rx_handler_func_t __rcu *rx_handler; void __rcu *rx_handler_data; @@ -3702,7 +3703,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, typedef int (*bpf_op_t)(struct net_device *dev, struct netdev_bpf *bpf); int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, - int fd, u32 flags); + int prog_fd, int chain_map_fd, u32 flags); u32 __dev_xdp_query(struct net_device *dev, bpf_op_t xdp_op, enum bpf_netdev_command cmd); int xdp_umem_query(struct net_device *dev, u16 queue_id); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 8aec8769d944..e7a704387608 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -976,6 +976,8 @@ enum { IFLA_XDP_DRV_PROG_ID, IFLA_XDP_SKB_PROG_ID, IFLA_XDP_HW_PROG_ID, + IFLA_XDP_CHAIN_MAP_FD, + IFLA_XDP_CHAIN_MAP_ID, __IFLA_XDP_MAX, }; diff --git a/net/core/dev.c b/net/core/dev.c index 7a456c6a7ad8..0aa5106339e7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8177,9 +8177,15 @@ static int dev_xdp_install(struct net_device *dev, bpf_op_t bpf_op, static void dev_xdp_uninstall(struct net_device *dev) { + struct bpf_map *chain_map = NULL; struct netdev_bpf xdp; bpf_op_t ndo_bpf; + /* Remove chain map */ + rcu_swap_protected(dev->xdp_chain_map, chain_map, 1); + if(chain_map) + bpf_map_put_with_uref(chain_map); + /* Remove generic XDP */ WARN_ON(dev_xdp_install(dev, generic_xdp_install, NULL, 0, NULL)); @@ -8207,15 +8213,17 @@ static void dev_xdp_uninstall(struct net_device *dev) * dev_change_xdp_fd - set or clear a bpf program for a device rx path * @dev: device * @extack: netlink extended ack - * @fd: new program fd or negative value to clear + * @prog_fd: new program fd or negative value to clear + * @chain_map_fd: new chain map fd or negative value to clear * @flags: xdp-related flags * * Set or clear a bpf program for a device */ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, - int fd, u32 flags) + int prog_fd, int chain_map_fd, u32 flags) { const struct net_device_ops *ops = dev->netdev_ops; + struct bpf_map *chain_map = NULL; enum bpf_netdev_command query; struct bpf_prog *prog = NULL; bpf_op_t bpf_op, bpf_chk; @@ -8237,7 +8245,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, if (bpf_op == bpf_chk) bpf_chk = generic_xdp_install; - if (fd >= 0) { + if (prog_fd >= 0) { u32 prog_id; if (!offload && __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG)) { @@ -8251,7 +8259,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, return -EBUSY; } - prog = bpf_prog_get_type_dev(fd, BPF_PROG_TYPE_XDP, + prog = bpf_prog_get_type_dev(prog_fd, BPF_PROG_TYPE_XDP, bpf_op == ops->ndo_bpf); if (IS_ERR(prog)) return PTR_ERR(prog); @@ -8267,13 +8275,35 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, return 0; } } else { + if (chain_map_fd >= 0) + return -EINVAL; + if (!__dev_xdp_query(dev, bpf_op, query)) return 0; } + if (chain_map_fd >= 0) { + chain_map = bpf_map_get_with_uref(chain_map_fd); + if (IS_ERR(chain_map)) + return PTR_ERR(chain_map); + + if (chain_map->map_type != BPF_MAP_TYPE_XDP_CHAIN) { + NL_SET_ERR_MSG(extack, "invalid chain map type"); + bpf_map_put_with_uref(chain_map); + return -EINVAL; + } + } + err = dev_xdp_install(dev, bpf_op, extack, flags, prog); - if (err < 0 && prog) - bpf_prog_put(prog); + if (err < 0) { + if (prog) + bpf_prog_put(prog); + } else { + rcu_swap_protected(dev->xdp_chain_map, chain_map, 1); + } + + if(chain_map) + bpf_map_put_with_uref(chain_map); return err; } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 49fa910b58af..d6123efdff80 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1427,6 +1427,7 @@ static int rtnl_xdp_report_one(struct sk_buff *skb, struct net_device *dev, static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev) { + struct bpf_map *chain_map; struct nlattr *xdp; u32 prog_id; int err; @@ -1461,6 +1462,13 @@ static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev) goto err_cancel; } + chain_map = rcu_dereference(dev->xdp_chain_map); + if (chain_map) { + err = nla_put_u32(skb, IFLA_XDP_CHAIN_MAP_ID, chain_map->id); + if (err) + goto err_cancel; + } + nla_nest_end(skb, xdp); return 0; @@ -2756,12 +2764,27 @@ static int do_setlink(const struct sk_buff *skb, } if (xdp[IFLA_XDP_FD]) { + int chain_map_fd = -1; + + if (xdp[IFLA_XDP_CHAIN_MAP_FD]) { + chain_map_fd = nla_get_s32(xdp[IFLA_XDP_CHAIN_MAP_FD]); + } else if (dev->xdp_chain_map) { + NL_SET_ERR_MSG(extack, "no chain map attribute, but chain map loaded"); + err = -EINVAL; + goto errout; + } + err = dev_change_xdp_fd(dev, extack, nla_get_s32(xdp[IFLA_XDP_FD]), + chain_map_fd, xdp_flags); if (err) goto errout; status |= DO_SETLINK_NOTIFY; + } else if (xdp[IFLA_XDP_CHAIN_MAP_FD]) { + err = -EINVAL; + NL_SET_ERR_MSG(extack, "chain map attribute invalid without prog fd"); + goto errout; } } From patchwork Wed Oct 2 13:30:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 1170660 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46jxph4Ptbz9sDB for ; Wed, 2 Oct 2019 23:30:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727952AbfJBNae (ORCPT ); Wed, 2 Oct 2019 09:30:34 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56780 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727919AbfJBNad (ORCPT ); Wed, 2 Oct 2019 09:30:33 -0400 Received: from mail-lf1-f72.google.com (mail-lf1-f72.google.com [209.85.167.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B383A2A09BB for ; Wed, 2 Oct 2019 13:30:32 +0000 (UTC) Received: by mail-lf1-f72.google.com with SMTP id p15so3476541lfc.20 for ; Wed, 02 Oct 2019 06:30:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=pbUUD2XJ6prV3zK1ZpK/kSetnSl9zt8sMAFPDgDE7Ng=; b=D6rna1GXPBczkI01xfFrK3NT98Qq9paATkCP7TbRaoS4vXqzSXP7pUloLu8Sm/nKL6 ZRKI+7T7eXIhtF7tRpZeY+i5gXz9nOOn//uyspRN/edemPuBb8oIs+vbjK6hv+MrPFuh nADtar5uS7juXFURHQbrKXlOzHv6jL3QhLvrlaP6hUVTg/1j7bdVHmZu8m8AdsCpm90Z vdV66IbKX4NjfGTAo05kbAbQxAyx17WVsgJFFVonp076+ydjUFguIViq7uxu2Pa2F6Xl 5kVjNifvPvhWL53J7Uxiopaqr4EDjPONRaE0YlHoxAhWbaURw2XHZ0BOCU5clxa3JPqw FMEA== X-Gm-Message-State: APjAAAWLAuSfmr9V9zAp+guTmwkrfM3gL1rT7ScCkeNE5vhYHcfTuhyM 7IE3OwkRh8Qp3u0p2E4fbXzYyIEkWEbybXL+uHEKtrH+c/kGVt0JtyCMXMP7SBo77w1CNNdIPao QA1yRLwgRrvjnqiNP X-Received: by 2002:ac2:495e:: with SMTP id o30mr2359180lfi.82.1570023030757; Wed, 02 Oct 2019 06:30:30 -0700 (PDT) X-Google-Smtp-Source: APXvYqw5cGmzdcKy5vmgUCN95vLcyGVAl1vnuile/NaWBL7pE5VNqrxdtSsdzExzBWCoeDUIG2wwQQ== X-Received: by 2002:ac2:495e:: with SMTP id o30mr2359165lfi.82.1570023030555; Wed, 02 Oct 2019 06:30:30 -0700 (PDT) Received: from alrua-x1.borgediget.toke.dk (borgediget.toke.dk. [85.204.121.218]) by smtp.gmail.com with ESMTPSA id n5sm6096592ljh.54.2019.10.02.06.30.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2019 06:30:29 -0700 (PDT) Received: by alrua-x1.borgediget.toke.dk (Postfix, from userid 1000) id 06C06180641; Wed, 2 Oct 2019 15:30:29 +0200 (CEST) Subject: [PATCH bpf-next 4/9] xdp: Implement chain call logic to support multiple programs on one interface From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: Daniel Borkmann Cc: Alexei Starovoitov , Martin KaFai Lau , Song Liu , Yonghong Song , Marek Majkowski , Lorenz Bauer , David Miller , Jesper Dangaard Brouer , netdev@vger.kernel.org, bpf@vger.kernel.org Date: Wed, 02 Oct 2019 15:30:28 +0200 Message-ID: <157002302894.1302756.12004905609124608227.stgit@alrua-x1> In-Reply-To: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> References: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Toke Høiland-Jørgensen This adds for executing multiple XDP programs on a single interface using the chain call map type introduced in the previous commits. The logic is added as an extension of bpf_prog_run_xdp() which will loop through the call sequence specified by the chain call map installed on the current interface. The overhead when no chain map is installed is only a single pointer dereference. The total call sequence length is limited to 32 programs, and the call sequence will be aborted and XDP_ABORTED returned if it is exceeded. Likewise, if a program in the sequence returns XDP_ABORTED, the whole sequence will be aborted immediately, on the assumption that this is a fault somewhere in the system. Signed-off-by: Toke Høiland-Jørgensen --- include/linux/filter.h | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/include/linux/filter.h b/include/linux/filter.h index 2ce57645f3cd..8a79ddd4f7b5 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -693,6 +693,7 @@ static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog, return res; } +#define BPF_XDP_MAX_CHAIN_CALLS 32 static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog, struct xdp_buff *xdp) { @@ -702,7 +703,30 @@ static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog, * already takes rcu_read_lock() when fetching the program, so * it's not necessary here anymore. */ - return BPF_PROG_RUN(prog, xdp); + + int i = BPF_XDP_MAX_CHAIN_CALLS; + struct bpf_map *chain_map; + u32 ret; + + chain_map = rcu_dereference(xdp->rxq->dev->xdp_chain_map); + if (!chain_map) + return BPF_PROG_RUN(prog, xdp); + + do { + if (!--i) { + ret = XDP_ABORTED; + goto out; + } + + ret = BPF_PROG_RUN(prog, xdp); + if (ret == XDP_ABORTED) + goto out; + + prog = bpf_xdp_chain_map_get_prog(chain_map, prog->aux->id, ret); + } while(prog); + +out: + return ret; } static inline u32 bpf_prog_insn_size(const struct bpf_prog *prog) From patchwork Wed Oct 2 13:30:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 1170661 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46jxph5nvrz9sPl for ; Wed, 2 Oct 2019 23:30:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727954AbfJBNae (ORCPT ); Wed, 2 Oct 2019 09:30:34 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57636 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727943AbfJBNae (ORCPT ); Wed, 2 Oct 2019 09:30:34 -0400 Received: from mail-lj1-f198.google.com (mail-lj1-f198.google.com [209.85.208.198]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 97DF96B for ; Wed, 2 Oct 2019 13:30:33 +0000 (UTC) Received: by mail-lj1-f198.google.com with SMTP id 205so4852914ljf.13 for ; Wed, 02 Oct 2019 06:30:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=m4Sgqjpq9WV+RhLcG+8KSrXV2gMjNXZLDdtwQU6v3z4=; b=BWpLWfFayRtN6P4nzJPwkA06xPzesmGPc93Wa9dvQdGaqYrUdobS1Dvtx1+hkRScqN orLlpaLJalYozb3Kyqq3Wqdbwjdg2h2nNufwFH33jC4TB8+zs6PGGgToyigAR45MO//U r4NHoX9l+FI6V9XzekGhoPD3FjAoyRxc/tIj4Cguwe0tD+LXxrzKsQb8ihWODQt3zUh2 hsc9hiiSJ974uOLWdhNNQJSLiVkznCxQ0f1tub5rOmvkuw05crieUDi9Y3iCoNwPkUJR D6WhY8mL0FkbBQoc2Ug2eFVKCT2AHwBRjFCZl4ihjM45sWfX+BYxmsIQmXOIbteY54X0 bK0w== X-Gm-Message-State: APjAAAUkbyTllwp06DFrlleFC9P/wc3XdlEZEUgJbLQBs//uLDphTyLA YQKVZHgolO9uGS5axPN+S0qtgxGKWmRJLBdVlcV6L7+67MxQ3i1vYANb42MKjrxKX1rbUHxsjkU IKNPc/W+vOdca X-Received: by 2002:a2e:5d98:: with SMTP id v24mr2651135lje.56.1570023032150; Wed, 02 Oct 2019 06:30:32 -0700 (PDT) X-Google-Smtp-Source: APXvYqw8cCkbNqL5TPDLmGDHggFEX6DkEsYyT6fJtdlXaqWq9FMXWMaNejYh7ICfgXbSYzvKA+MfaA== X-Received: by 2002:a2e:5d98:: with SMTP id v24mr2651117lje.56.1570023032001; Wed, 02 Oct 2019 06:30:32 -0700 (PDT) Received: from alrua-x1.borgediget.toke.dk (borgediget.toke.dk. [85.204.121.218]) by smtp.gmail.com with ESMTPSA id y204sm4601049lfa.64.2019.10.02.06.30.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2019 06:30:31 -0700 (PDT) Received: by alrua-x1.borgediget.toke.dk (Postfix, from userid 1000) id 1A9D6180642; Wed, 2 Oct 2019 15:30:30 +0200 (CEST) Subject: [PATCH bpf-next 5/9] tools/include/uapi: Add XDP chain map definitions From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: Daniel Borkmann Cc: Alexei Starovoitov , Martin KaFai Lau , Song Liu , Yonghong Song , Marek Majkowski , Lorenz Bauer , David Miller , Jesper Dangaard Brouer , netdev@vger.kernel.org, bpf@vger.kernel.org Date: Wed, 02 Oct 2019 15:30:30 +0200 Message-ID: <157002303003.1302756.7196736864367141657.stgit@alrua-x1> In-Reply-To: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> References: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org From: Toke Høiland-Jørgensen This syncs the XDP chain-map related UAPI definitions into tools/include/uapi. Signed-off-by: Toke Høiland-Jørgensen --- tools/include/uapi/linux/bpf.h | 12 ++++++++++++ tools/include/uapi/linux/if_link.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 77c6be96d676..8b336fb68880 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -136,6 +136,7 @@ enum bpf_map_type { BPF_MAP_TYPE_STACK, BPF_MAP_TYPE_SK_STORAGE, BPF_MAP_TYPE_DEVMAP_HASH, + BPF_MAP_TYPE_XDP_CHAIN, }; /* Note that tracing related programs such as @@ -3153,6 +3154,17 @@ enum xdp_action { XDP_PASS, XDP_TX, XDP_REDIRECT, + + __XDP_ACT_MAX /* leave at end */ +}; +#define XDP_ACT_MAX (__XDP_ACT_MAX - 1) + +struct xdp_chain_acts { + __u32 wildcard_act; + __u32 drop_act; + __u32 pass_act; + __u32 tx_act; + __u32 redirect_act; }; /* user accessible metadata for XDP packet hook diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h index 4a8c02cafa9a..7387d2371489 100644 --- a/tools/include/uapi/linux/if_link.h +++ b/tools/include/uapi/linux/if_link.h @@ -974,6 +974,8 @@ enum { IFLA_XDP_DRV_PROG_ID, IFLA_XDP_SKB_PROG_ID, IFLA_XDP_HW_PROG_ID, + IFLA_XDP_CHAIN_MAP_FD, + IFLA_XDP_CHAIN_MAP_ID, __IFLA_XDP_MAX, }; From patchwork Wed Oct 2 13:30:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 1170662 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46jxpj3KFZz9sPq for ; Wed, 2 Oct 2019 23:30:37 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727970AbfJBNag (ORCPT ); Wed, 2 Oct 2019 09:30:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52294 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727933AbfJBNaf (ORCPT ); Wed, 2 Oct 2019 09:30:35 -0400 Received: from mail-lj1-f199.google.com (mail-lj1-f199.google.com [209.85.208.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 43D062BF7B for ; Wed, 2 Oct 2019 13:30:35 +0000 (UTC) Received: by mail-lj1-f199.google.com with SMTP id i18so1230015ljg.14 for ; Wed, 02 Oct 2019 06:30:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=Z3aw7R0clnfnDQPZcECbnXLHG6G+LnnHD4YWuHpSSVE=; b=DtxsQWPM9Qt7fV4WD/FWNmBoE7jeETv66VY/AWIFbFis207EMjtjMeFdWZGVXtnMuh mZ9kGX8IHnYNIIar9uFRUITMeCRTWRK+PGCnWyw3hBNwGDNucooitgNS7L6CpDPRbgj7 BJMa4U3tFzHBkvGBnMMx1+6td1+IuHabvGBeXUHlTr/1d0zzEV+wtkLp4XsgsKjcgEcJ 7KEoKkVF6zaArxbAKP+ahb0TezYFcfA1fNF9XDn1JBcxn8ZcN69pqKpMPeHQHbs5dkf1 95RPaGdMsLKoelK2Rx2KxLrfu9aavnMEIWn98pYiZjJ0hnUbgqm8jnfB+16YdEsTyNhv CPSQ== X-Gm-Message-State: APjAAAWCoynleYWkwKqu73ZJdpepEJaki1lhGQWNj0APvf9S/pVrM3bj iaDFWmF8VC4BkwWyDPfjTIcvK6zSUicW2u1xsJVdvBbNd7OEtKFAtzb/uEgNWpaKQ84HObxxj3g ajHZ3UcGgc1Cl X-Received: by 2002:a2e:9006:: with SMTP id h6mr2573547ljg.42.1570023033807; Wed, 02 Oct 2019 06:30:33 -0700 (PDT) X-Google-Smtp-Source: APXvYqykYZitPBp52SAOEI1k3J6U6u675MDEHLsa2zNAbHjI31o6qorB+plXloTHn1REs97Npunwdg== X-Received: by 2002:a2e:9006:: with SMTP id h6mr2573536ljg.42.1570023033652; Wed, 02 Oct 2019 06:30:33 -0700 (PDT) Received: from alrua-x1.borgediget.toke.dk (borgediget.toke.dk. [85.204.121.218]) by smtp.gmail.com with ESMTPSA id q24sm4523587lfa.94.2019.10.02.06.30.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2019 06:30:33 -0700 (PDT) Received: by alrua-x1.borgediget.toke.dk (Postfix, from userid 1000) id 2F4BC18063D; Wed, 2 Oct 2019 15:30:31 +0200 (CEST) Subject: [PATCH bpf-next 6/9] tools/libbpf_probes: Add support for xdp_chain map type From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: Daniel Borkmann Cc: Alexei Starovoitov , Martin KaFai Lau , Song Liu , Yonghong Song , Marek Majkowski , Lorenz Bauer , David Miller , Jesper Dangaard Brouer , netdev@vger.kernel.org, bpf@vger.kernel.org Date: Wed, 02 Oct 2019 15:30:31 +0200 Message-ID: <157002303111.1302756.273260839640273673.stgit@alrua-x1> In-Reply-To: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> References: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org From: Toke Høiland-Jørgensen This adds support for the BPF_MAP_TYPE_XDP_CHAIN map type to libbpf_probes.c. Signed-off-by: Toke Høiland-Jørgensen --- tools/lib/bpf/libbpf_probes.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c index 4b0b0364f5fc..266ae6e78f88 100644 --- a/tools/lib/bpf/libbpf_probes.c +++ b/tools/lib/bpf/libbpf_probes.c @@ -231,6 +231,10 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex) if (btf_fd < 0) return false; break; + case BPF_MAP_TYPE_XDP_CHAIN: + key_size = sizeof(__u32); + value_size = sizeof(struct xdp_chain_acts); + break; case BPF_MAP_TYPE_UNSPEC: case BPF_MAP_TYPE_HASH: case BPF_MAP_TYPE_ARRAY: From patchwork Wed Oct 2 13:30:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 1170668 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46jxpp4JYzz9sPl for ; Wed, 2 Oct 2019 23:30:42 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727995AbfJBNaj (ORCPT ); Wed, 2 Oct 2019 09:30:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38156 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727973AbfJBNag (ORCPT ); Wed, 2 Oct 2019 09:30:36 -0400 Received: from mail-lf1-f71.google.com (mail-lf1-f71.google.com [209.85.167.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 25E333D94D for ; Wed, 2 Oct 2019 13:30:36 +0000 (UTC) Received: by mail-lf1-f71.google.com with SMTP id q3so3550275lfc.5 for ; Wed, 02 Oct 2019 06:30:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=pqLC3K0zosC/Ijfelepo4fx24olc2AqeXpVeWBxBt4o=; b=BpLaXOuQsC/FwGvSRwIyD7QeIiiiteVYNxK7Oxt4hXUs66uuZcsUt7Hhy8+ZVwB/Q/ mgb0e+Hm7e7LakyR2e9wzCncTdMmZe205DMQ//WOhrkOnKNu7f//SDfeVzzVffc0pFY/ 9jkfqaQZN+uHsOjtkZmNC4NZv7DJW12vLvV+oplA9wud5Rwfm+wd0Smt5lVLYynKRuaE 6Kr1Ytd0P79nvrxax+x9opfQTulVYsPdKF3zmDVR9XiSPbMu2+jvH6sgb9ZmXzmjD5yc Px60BomYR29VRire6B2ABiFeG9ccPmoz55S1KRzrbBqcLMz/o3e/ox+YW1tGVTU/A1nP mQBQ== X-Gm-Message-State: APjAAAV47Slf+/ys63W6LKA1K/KxB83515fraeD2/n2/5lzJZX7dBS1D ZXADTEDUqc93VujN+CVtaqVeEG1dx8r9I8vZfB7dgPt4RSL/XXKnjUVc/io+Ai9r0yeQhwtMZyM tsimXtelEf05O X-Received: by 2002:a19:ef17:: with SMTP id n23mr2264339lfh.109.1570023034730; Wed, 02 Oct 2019 06:30:34 -0700 (PDT) X-Google-Smtp-Source: APXvYqyf+i0aehSnS03SCOX01y6ZKk/kXFw701LZVoGDGz5WSDlfP1vxr3k6yYRK8vjW24yO32CIcQ== X-Received: by 2002:a19:ef17:: with SMTP id n23mr2264329lfh.109.1570023034557; Wed, 02 Oct 2019 06:30:34 -0700 (PDT) Received: from alrua-x1.borgediget.toke.dk ([2a00:7660:6da:443::2]) by smtp.gmail.com with ESMTPSA id c16sm4543320lfj.8.2019.10.02.06.30.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2019 06:30:33 -0700 (PDT) Received: by alrua-x1.borgediget.toke.dk (Postfix, from userid 1000) id 46661180641; Wed, 2 Oct 2019 15:30:32 +0200 (CEST) Subject: [PATCH bpf-next 7/9] bpftool: Add definitions for xdp_chain map type From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: Daniel Borkmann Cc: Alexei Starovoitov , Martin KaFai Lau , Song Liu , Yonghong Song , Marek Majkowski , Lorenz Bauer , David Miller , Jesper Dangaard Brouer , netdev@vger.kernel.org, bpf@vger.kernel.org Date: Wed, 02 Oct 2019 15:30:32 +0200 Message-ID: <157002303220.1302756.13509533392771604835.stgit@alrua-x1> In-Reply-To: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> References: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org From: Toke Høiland-Jørgensen Adds bash completion and definition types for the xdp_chain map type to bpftool. Signed-off-by: Toke Høiland-Jørgensen --- tools/bpf/bpftool/Documentation/bpftool-map.rst | 4 ++-- tools/bpf/bpftool/bash-completion/bpftool | 2 +- tools/bpf/bpftool/map.c | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst index 1c0f7146aab0..9aefcef50b53 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-map.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst @@ -47,8 +47,8 @@ MAP COMMANDS | *TYPE* := { **hash** | **array** | **prog_array** | **perf_event_array** | **percpu_hash** | | **percpu_array** | **stack_trace** | **cgroup_array** | **lru_hash** | | **lru_percpu_hash** | **lpm_trie** | **array_of_maps** | **hash_of_maps** -| | **devmap** | **devmap_hash** | **sockmap** | **cpumap** | **xskmap** | **sockhash** -| | **cgroup_storage** | **reuseport_sockarray** | **percpu_cgroup_storage** +| | **devmap** | **devmap_hash** | **xdp_chain** | **sockmap** | **cpumap** | **xskmap** +| | **sockhash** | **cgroup_storage** | **reuseport_sockarray** | **percpu_cgroup_storage** | | **queue** | **stack** } DESCRIPTION diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 70493a6da206..95f19191b8d1 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -489,7 +489,7 @@ _bpftool() perf_event_array percpu_hash percpu_array \ stack_trace cgroup_array lru_hash \ lru_percpu_hash lpm_trie array_of_maps \ - hash_of_maps devmap devmap_hash sockmap cpumap \ + hash_of_maps devmap devmap_hash xdp_chain sockmap cpumap \ xskmap sockhash cgroup_storage reuseport_sockarray \ percpu_cgroup_storage queue stack' -- \ "$cur" ) ) diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index de61d73b9030..97b5b42df79c 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -38,6 +38,7 @@ const char * const map_type_name[] = { [BPF_MAP_TYPE_HASH_OF_MAPS] = "hash_of_maps", [BPF_MAP_TYPE_DEVMAP] = "devmap", [BPF_MAP_TYPE_DEVMAP_HASH] = "devmap_hash", + [BPF_MAP_TYPE_XDP_CHAIN] = "xdp_chain", [BPF_MAP_TYPE_SOCKMAP] = "sockmap", [BPF_MAP_TYPE_CPUMAP] = "cpumap", [BPF_MAP_TYPE_XSKMAP] = "xskmap", @@ -1326,7 +1327,7 @@ static int do_help(int argc, char **argv) " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n" " percpu_array | stack_trace | cgroup_array | lru_hash |\n" " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n" - " devmap | devmap_hash | sockmap | cpumap | xskmap | sockhash |\n" + " devmap | devmap_hash | xdp_chain | sockmap | cpumap | xskmap | sockhash |\n" " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage }\n" " " HELP_SPEC_OPTIONS "\n" "", From patchwork Wed Oct 2 13:30:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 1170664 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46jxpm2tb0z9sPl for ; Wed, 2 Oct 2019 23:30:40 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727982AbfJBNaj (ORCPT ); Wed, 2 Oct 2019 09:30:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57674 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727981AbfJBNai (ORCPT ); Wed, 2 Oct 2019 09:30:38 -0400 Received: from mail-lf1-f69.google.com (mail-lf1-f69.google.com [209.85.167.69]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8CBD5550BB for ; Wed, 2 Oct 2019 13:30:37 +0000 (UTC) Received: by mail-lf1-f69.google.com with SMTP id n5so3545084lfi.0 for ; Wed, 02 Oct 2019 06:30:37 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=9HOtLr1nND6QqUI8Q8VdibuQQQmxuKzuYOHS9mRlR1E=; b=GWizkYkkRt3Di9oKJw98OALx9JkO78mZqqtSDAoyTHVWNjlUXKmxpOjn9i8Fyykwc0 1MmvgvAA3GNFZGDwPg+PPvUfhOQcmfLpiRLX4AXjbe+lYaGaznewbCDQUxWO43+OsOF9 9ZLG5A828RQkQ6bbVkpu6JpOoZg7Fjh2wj1lFIdh9pB+LygFgxSpLDyq4hF8lo/93VtB 3FJQR2RboOE/iO7kYl+PVb3DIG7525owakMgCl8TsZx8TOBouWwHqedykPbeplvVgV27 6Rg7Mww5TPt3qed9uFZf8T0L//J2J8CzQsAhDsd18AxmxWVUVzCWQgHhoKf6UrJftWa4 GrGA== X-Gm-Message-State: APjAAAWEuOyrrBn6MPRZseWyYgP9f6/YYKWYRlLbD4oxwDnW4AHcpy6I wTvkSXv8mVf8+eS1W8MFqO5yyTwCp+jVeszLKIZPV8Uk6QVpvi9J3KxVmPLs6F+1Vupuq8ASoMn TVIsMDLvACmOC X-Received: by 2002:a19:f111:: with SMTP id p17mr2355939lfh.187.1570023036089; Wed, 02 Oct 2019 06:30:36 -0700 (PDT) X-Google-Smtp-Source: APXvYqy9kGDVLmWBlBvzv2M3kxJrEQfwC6ZwPk5RsZde6tZUzWzlKrvuyJvNTEy7zCPgqiLgNzPocA== X-Received: by 2002:a19:f111:: with SMTP id p17mr2355926lfh.187.1570023035866; Wed, 02 Oct 2019 06:30:35 -0700 (PDT) Received: from alrua-x1.borgediget.toke.dk ([2a00:7660:6da:443::2]) by smtp.gmail.com with ESMTPSA id s6sm145355ljg.43.2019.10.02.06.30.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2019 06:30:34 -0700 (PDT) Received: by alrua-x1.borgediget.toke.dk (Postfix, from userid 1000) id 5B94F180640; Wed, 2 Oct 2019 15:30:33 +0200 (CEST) Subject: [PATCH bpf-next 8/9] libbpf: Add support for setting and getting XDP chain maps From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: Daniel Borkmann Cc: Alexei Starovoitov , Martin KaFai Lau , Song Liu , Yonghong Song , Marek Majkowski , Lorenz Bauer , David Miller , Jesper Dangaard Brouer , netdev@vger.kernel.org, bpf@vger.kernel.org Date: Wed, 02 Oct 2019 15:30:33 +0200 Message-ID: <157002303329.1302756.18388939731361871849.stgit@alrua-x1> In-Reply-To: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> References: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org From: Toke Høiland-Jørgensen This adds two new API functions for setting and getting XDP programs with associated chain map IDs. Programs are expected to pair them, so that if a program uses the chain map-aware setter, it should also use the associated getter. Programs using the old non-chain aware variants of the functions will not set the XDP chain map attribute on the netlink message, resulting in the kernel rejecting the command if a chain map has already been loaded. Signed-off-by: Toke Høiland-Jørgensen --- tools/lib/bpf/libbpf.h | 4 ++++ tools/lib/bpf/libbpf.map | 2 ++ tools/lib/bpf/netlink.c | 49 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index e8f70977d137..0a459840e32c 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -357,7 +357,11 @@ LIBBPF_API int bpf_prog_load(const char *file, enum bpf_prog_type type, struct bpf_object **pobj, int *prog_fd); LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags); +LIBBPF_API int bpf_set_link_xdp_chain(int ifindex, int prog_fd, int chain_map_fd, + __u32 flags); LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags); +LIBBPF_API int bpf_get_link_xdp_chain(int ifindex, __u32 *prog_id, __u32 *chain_map_id, + __u32 flags); struct perf_buffer; diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 8d10ca03d78d..59f412680292 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -192,4 +192,6 @@ LIBBPF_0.0.5 { } LIBBPF_0.0.4; LIBBPF_0.0.6 { + bpf_set_link_xdp_chain; + bpf_get_link_xdp_chain; } LIBBPF_0.0.5; diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c index ce3ec81b71c0..c6f63bdab2e6 100644 --- a/tools/lib/bpf/netlink.c +++ b/tools/lib/bpf/netlink.c @@ -25,6 +25,7 @@ struct xdp_id_md { int ifindex; __u32 flags; __u32 id; + __u32 chain_map_id; }; int libbpf_netlink_open(__u32 *nl_pid) @@ -128,7 +129,8 @@ static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq, return ret; } -int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) +static int __bpf_set_link_xdp_fd(int ifindex, int *prog_fd, int *chain_map_fd, + __u32 flags) { int sock, seq = 0, ret; struct nlattr *nla, *nla_xdp; @@ -162,9 +164,19 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); nla_xdp->nla_type = IFLA_XDP_FD; nla_xdp->nla_len = NLA_HDRLEN + sizeof(int); - memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd)); + memcpy((char *)nla_xdp + NLA_HDRLEN, prog_fd, sizeof(*prog_fd)); nla->nla_len += nla_xdp->nla_len; + if (chain_map_fd) { + /* add XDP chain map */ + nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); + nla_xdp->nla_type = IFLA_XDP_CHAIN_MAP_FD; + nla_xdp->nla_len = NLA_HDRLEN + sizeof(int); + memcpy((char *)nla_xdp + NLA_HDRLEN, chain_map_fd, + sizeof(*chain_map_fd)); + nla->nla_len += nla_xdp->nla_len; + } + /* if user passed in any flags, add those too */ if (flags) { nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len); @@ -187,6 +199,17 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) return ret; } +int bpf_set_link_xdp_chain(int ifindex, int prog_fd, int chain_map_fd, + __u32 flags) +{ + return __bpf_set_link_xdp_fd(ifindex, &prog_fd, &chain_map_fd, flags); +} + +int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags) +{ + return __bpf_set_link_xdp_fd(ifindex, &fd, NULL, flags); +} + static int __dump_link_nlmsg(struct nlmsghdr *nlh, libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie) { @@ -247,10 +270,13 @@ static int get_xdp_id(void *cookie, void *msg, struct nlattr **tb) xdp_id->id = libbpf_nla_getattr_u32(xdp_tb[xdp_attr]); + if (xdp_tb[IFLA_XDP_CHAIN_MAP_ID]) + xdp_id->chain_map_id = libbpf_nla_getattr_u32(xdp_tb[IFLA_XDP_CHAIN_MAP_ID]); + return 0; } -int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags) +static int __bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 *chain_map_id, __u32 flags) { struct xdp_id_md xdp_id = {}; int sock, ret; @@ -274,13 +300,28 @@ int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags) xdp_id.flags = flags; ret = libbpf_nl_get_link(sock, nl_pid, get_xdp_id, &xdp_id); - if (!ret) + if (!ret) { *prog_id = xdp_id.id; + if (chain_map_id) + *chain_map_id = xdp_id.chain_map_id; + } + close(sock); return ret; } +int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags) +{ + return __bpf_get_link_xdp_id(ifindex, prog_id, NULL, flags); +} + +int bpf_get_link_xdp_chain(int ifindex, __u32 *prog_id, __u32 *chain_map_id, + __u32 flags) +{ + return __bpf_get_link_xdp_id(ifindex, prog_id, chain_map_id, flags); +} + int libbpf_nl_get_link(int sock, unsigned int nl_pid, libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie) { From patchwork Wed Oct 2 13:30:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= X-Patchwork-Id: 1170670 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46jxpq3gBFz9sPx for ; Wed, 2 Oct 2019 23:30:43 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728000AbfJBNal (ORCPT ); Wed, 2 Oct 2019 09:30:41 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56810 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727983AbfJBNaj (ORCPT ); Wed, 2 Oct 2019 09:30:39 -0400 Received: from mail-lf1-f71.google.com (mail-lf1-f71.google.com [209.85.167.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9CDFB2A09A3 for ; Wed, 2 Oct 2019 13:30:38 +0000 (UTC) Received: by mail-lf1-f71.google.com with SMTP id x20so3486937lfe.14 for ; Wed, 02 Oct 2019 06:30:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=QLC9KwHSSP3dhfBbVJm+BVSNFOakztKyUFvjkUTpYiQ=; b=ZZZOnYFqTuwD75ZlP2muVIxF+ITKFW16+48jz4IPd0v4Kg+J8wkVwC67nb2kD4LOMw vITggJ4rz4Tv1w3ld5NxtjBYLq75Tx6PldLn2LK3Ar6/0PdXJxIYy8iR67YQTFWr/aNN lWA+OdsM/d3VkUJPWH/FKkFPdUd48rSiVHtuiTDI+DhfKZH3XkDgGNNd/AyCENJJgaJP wsl6zl1Pqq+B7SfSdIAqqZGZ/NBJivUruav5OaV5ZQHI5MykzboFRtRtYUEbudB3+mGy 2KhYRb5ww1PovY4l3tXTieYNR+EhuOMlzEv1ZZFGHZh41n0NK3947Sqpy32WHAC2QlwC nzcg== X-Gm-Message-State: APjAAAXVQoOPSKnNkauytmsY5FPF7Ys12EwgoesKbw2hAoL88t6IM7Fm iPUSPj5PhjmyGg0OZNKgawar3mMuPK1mo6nM9Vq4lJ4QQh5B+uzhDFbR8Wp2vLbw228ShmvCsvw qtzmB3YDjMwWi X-Received: by 2002:ac2:5e9e:: with SMTP id b30mr2372180lfq.5.1570023037040; Wed, 02 Oct 2019 06:30:37 -0700 (PDT) X-Google-Smtp-Source: APXvYqzD9afo3HryJaCSf2PTBfYvUaWyIdp3d7VblL0TOAP5DSUMHNF6cs/y3+8Dztzb/0Hnq6iXKQ== X-Received: by 2002:ac2:5e9e:: with SMTP id b30mr2372148lfq.5.1570023036632; Wed, 02 Oct 2019 06:30:36 -0700 (PDT) Received: from alrua-x1.borgediget.toke.dk (borgediget.toke.dk. [85.204.121.218]) by smtp.gmail.com with ESMTPSA id m8sm4566785lfa.67.2019.10.02.06.30.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2019 06:30:35 -0700 (PDT) Received: by alrua-x1.borgediget.toke.dk (Postfix, from userid 1000) id 7236418063D; Wed, 2 Oct 2019 15:30:34 +0200 (CEST) Subject: [PATCH bpf-next 9/9] selftests: Add tests for XDP chain calls From: =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= To: Daniel Borkmann Cc: Alexei Starovoitov , Martin KaFai Lau , Song Liu , Yonghong Song , Marek Majkowski , Lorenz Bauer , David Miller , Jesper Dangaard Brouer , netdev@vger.kernel.org, bpf@vger.kernel.org Date: Wed, 02 Oct 2019 15:30:34 +0200 Message-ID: <157002303437.1302756.12935236773789755295.stgit@alrua-x1> In-Reply-To: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> References: <157002302448.1302756.5727756706334050763.stgit@alrua-x1> User-Agent: StGit/0.19-dirty MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org From: Toke Høiland-Jørgensen This adds new self tests for the XDP chain call functionality. Signed-off-by: Toke Høiland-Jørgensen --- tools/testing/selftests/bpf/.gitignore | 1 tools/testing/selftests/bpf/Makefile | 3 tools/testing/selftests/bpf/progs/xdp_dummy.c | 6 + tools/testing/selftests/bpf/test_maps.c | 45 ++++ tools/testing/selftests/bpf/test_xdp_chain.sh | 77 +++++++ tools/testing/selftests/bpf/xdp_chain.c | 271 +++++++++++++++++++++++++ 6 files changed, 402 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/bpf/test_xdp_chain.sh create mode 100644 tools/testing/selftests/bpf/xdp_chain.c diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore index 7470327edcfe..e9d2d765cc8f 100644 --- a/tools/testing/selftests/bpf/.gitignore +++ b/tools/testing/selftests/bpf/.gitignore @@ -39,3 +39,4 @@ libbpf.so.* test_hashmap test_btf_dump xdping +xdp_chain diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 6889c19a628c..97e8f6ae4a15 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -29,7 +29,7 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test test_sock test_btf test_sockmap get_cgroup_id_user test_socket_cookie \ test_cgroup_storage test_select_reuseport test_section_names \ test_netcnt test_tcpnotify_user test_sock_fields test_sysctl test_hashmap \ - test_btf_dump test_cgroup_attach xdping + test_btf_dump test_cgroup_attach xdping xdp_chain BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c))) TEST_GEN_FILES = $(BPF_OBJ_FILES) @@ -71,6 +71,7 @@ TEST_PROGS := test_kmod.sh \ test_tc_tunnel.sh \ test_tc_edt.sh \ test_xdping.sh \ + test_xdp_chain.sh \ test_bpftool_build.sh TEST_PROGS_EXTENDED := with_addr.sh \ diff --git a/tools/testing/selftests/bpf/progs/xdp_dummy.c b/tools/testing/selftests/bpf/progs/xdp_dummy.c index 43b0ef1001ed..454a1f0763a1 100644 --- a/tools/testing/selftests/bpf/progs/xdp_dummy.c +++ b/tools/testing/selftests/bpf/progs/xdp_dummy.c @@ -10,4 +10,10 @@ int xdp_dummy_prog(struct xdp_md *ctx) return XDP_PASS; } +SEC("xdp_drop") +int xdp_drop_prog(struct xdp_md *ctx) +{ + return XDP_DROP; +} + char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c index e1f1becda529..44f2f8548a24 100644 --- a/tools/testing/selftests/bpf/test_maps.c +++ b/tools/testing/selftests/bpf/test_maps.c @@ -523,6 +523,50 @@ static void test_devmap_hash(unsigned int task, void *data) close(fd); } +static void test_xdp_chain_map(unsigned int task, void *data) +{ + const char *file = "./xdp_dummy.o"; + struct xdp_chain_acts acts = {}; + struct bpf_object *obj; + int map_fd, prog_fd; + __u32 key = 0; + int err; + + map_fd = bpf_create_map(BPF_MAP_TYPE_XDP_CHAIN, sizeof(key), sizeof(acts), + 2, 0); + if (map_fd < 0) { + printf("Failed to create xdp_chain map '%s'!\n", strerror(errno)); + exit(1); + } + + err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd); + if (err < 0) { + printf("Failed to load dummy prog: '%s'!\n", strerror(errno)); + exit(1); + } + + /* Try inserting NULL key/value - should fail */ + assert(bpf_map_update_elem(map_fd, &key, &acts, 0) == -1 && errno == EINVAL); + + /* Try inserting NULL value - should fail */ + key = 1; + assert(bpf_map_update_elem(map_fd, &key, &acts, 0) == -1 && errno == EINVAL); + + /* Try a real insert - should succeed */ + acts.wildcard_act = prog_fd; + assert(bpf_map_update_elem(map_fd, &key, &acts, 0) == 0); + + /* Replace with full table */ + acts.drop_act = acts.pass_act = acts.tx_act = acts.redirect_act = prog_fd; + assert(bpf_map_update_elem(map_fd, &key, &acts, 0) == 0); + + /* Try deleting element */ + assert(bpf_map_delete_elem(map_fd, &key) == 0); + + bpf_object__close(obj); + close(map_fd); +} + static void test_queuemap(unsigned int task, void *data) { const int MAP_SIZE = 32; @@ -1700,6 +1744,7 @@ static void run_all_tests(void) test_devmap(0, NULL); test_devmap_hash(0, NULL); + test_xdp_chain_map(0, NULL); test_sockmap(0, NULL); test_map_large(); diff --git a/tools/testing/selftests/bpf/test_xdp_chain.sh b/tools/testing/selftests/bpf/test_xdp_chain.sh new file mode 100755 index 000000000000..3997655d4e45 --- /dev/null +++ b/tools/testing/selftests/bpf/test_xdp_chain.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# xdp_chain tests +# Here we setup and teardown configuration required to run +# xdp_chain, exercising its options. +# +# Setup is similar to xdping tests. +# +# Topology: +# --------- +# root namespace | tc_ns0 namespace +# | +# ---------- | ---------- +# | veth1 | --------- | veth0 | +# ---------- peer ---------- +# +# Device Configuration +# -------------------- +# Root namespace with BPF +# Device names and addresses: +# veth1 IP: 10.1.1.200 +# +# Namespace tc_ns0 with BPF +# Device names and addresses: +# veth0 IPv4: 10.1.1.100 +# xdp_chain binary run inside this +# + +readonly TARGET_IP="10.1.1.100" +readonly TARGET_NS="xdp_ns0" + +readonly LOCAL_IP="10.1.1.200" + +setup() +{ + ip netns add $TARGET_NS + ip link add veth0 type veth peer name veth1 + ip link set veth0 netns $TARGET_NS + ip netns exec $TARGET_NS ip addr add ${TARGET_IP}/24 dev veth0 + ip addr add ${LOCAL_IP}/24 dev veth1 + ip netns exec $TARGET_NS ip link set veth0 up + ip link set veth1 up +} + +cleanup() +{ + set +e + ip netns delete $TARGET_NS 2>/dev/null + ip link del veth1 2>/dev/null +} + +die() +{ + echo "$@" >&2 + exit 1 +} + +test() +{ + args="$1" + + ip netns exec $TARGET_NS ./xdp_chain $args || die "XDP chain test error" +} + +set -e + +server_pid=0 + +trap cleanup EXIT + +setup + +test "-I veth0 -S $LOCAL_IP" + +echo "OK. All tests passed" +exit 0 diff --git a/tools/testing/selftests/bpf/xdp_chain.c b/tools/testing/selftests/bpf/xdp_chain.c new file mode 100644 index 000000000000..11f78bb1c2e7 --- /dev/null +++ b/tools/testing/selftests/bpf/xdp_chain.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bpf/bpf.h" +#include "bpf/libbpf.h" + +static int ifindex; +static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; +static char *dest = NULL, *ifname = NULL; + +static void cleanup(int sig) +{ + int ret; + + fprintf(stderr, " Cleaning up\n"); + if ((ret = bpf_set_link_xdp_chain(ifindex, -1, -1, xdp_flags))) + fprintf(stderr, "Warning: Unable to clear XDP prog: %s\n", + strerror(-ret)); + if (sig) + exit(1); +} + +static void show_usage(const char *prog) +{ + fprintf(stderr, + "usage: %s [OPTS] -I interface destination\n\n" + "OPTS:\n" + " -I interface interface name\n" + " -N Run in driver mode\n" + " -S Run in skb mode\n" + " -p pin_path path to pin chain call map\n" + " -x Exit after setup\n" + " -c Cleanup and exit\n", + prog); +} + +static int run_ping(bool should_fail, const char *msg) +{ + char cmd[256]; + bool success; + int ret; + + snprintf(cmd, sizeof(cmd), "ping -c 1 -W 1 -I %s %s >/dev/null", ifname, dest); + + printf(" %s: ", msg); + + ret = system(cmd); + + success = (!!ret == should_fail); + printf(success ? "PASS\n" : "FAIL\n"); + + return !success; +} + +int main(int argc, char **argv) +{ + __u32 mode_flags = XDP_FLAGS_DRV_MODE | XDP_FLAGS_SKB_MODE; + int pass_prog_fd = -1, drop_prog_fd = -1, map_fd = -1; + const char *filename = "xdp_dummy.o", *pin_path = NULL; + struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; + struct bpf_program *pass_prog, *drop_prog; + __u32 map_key, prog_id, chain_map_id; + struct xdp_chain_acts acts = {}; + struct bpf_prog_info info = {}; + __u32 info_len = sizeof(info); + const char *optstr = "I:NSp:xc"; + bool setup_only = false, cleanup_only = false; + struct bpf_object *obj; + int opt, ret = 1; + + while ((opt = getopt(argc, argv, optstr)) != -1) { + switch (opt) { + case 'I': + ifname = optarg; + ifindex = if_nametoindex(ifname); + if (!ifindex) { + fprintf(stderr, "Could not get interface %s\n", + ifname); + return 1; + } + break; + case 'N': + xdp_flags |= XDP_FLAGS_DRV_MODE; + break; + case 'S': + xdp_flags |= XDP_FLAGS_SKB_MODE; + break; + case 'x': + setup_only = true; + break; + case 'c': + cleanup_only = true; + break; + case 'p': + pin_path = optarg; + break; + default: + show_usage(basename(argv[0])); + return 1; + } + } + + if (!ifname) { + show_usage(basename(argv[0])); + return 1; + } + + if (cleanup_only) { + if (pin_path) + unlink(pin_path); + cleanup(0); + return 0; + } + + if (!setup_only && optind == argc) { + show_usage(basename(argv[0])); + return 1; + } + dest = argv[optind]; + + if ((xdp_flags & mode_flags) == mode_flags) { + fprintf(stderr, "-N or -S can be specified, not both.\n"); + show_usage(basename(argv[0])); + return 1; + } + + if (setrlimit(RLIMIT_MEMLOCK, &r)) { + perror("setrlimit(RLIMIT_MEMLOCK)"); + return 1; + } + + if (bpf_prog_load(filename, BPF_PROG_TYPE_XDP, &obj, &pass_prog_fd)) { + fprintf(stderr, "load of %s failed\n", filename); + return 1; + } + + pass_prog = bpf_object__find_program_by_title(obj, "xdp_dummy"); + drop_prog = bpf_object__find_program_by_title(obj, "xdp_drop"); + + if (!pass_prog || !drop_prog) { + fprintf(stderr, "could not find xdp programs\n"); + return 1; + } + pass_prog_fd = bpf_program__fd(pass_prog); + drop_prog_fd = bpf_program__fd(drop_prog); + if (pass_prog_fd < 0 || drop_prog_fd < 0) { + fprintf(stderr, "could not find xdp programs\n"); + goto done; + } + + ret = bpf_obj_get_info_by_fd(pass_prog_fd, &info, &info_len); + if (ret) { + fprintf(stderr, "unable to get program ID from kernel\n"); + goto done; + } + map_key = info.id; + map_fd = bpf_create_map(BPF_MAP_TYPE_XDP_CHAIN, + sizeof(map_key), sizeof(acts), + 2, 0); + + if (map_fd < 0) { + fprintf(stderr, "unable to create chain call map: %s\n", strerror(errno)); + goto done; + } + + if (pin_path && (ret = bpf_obj_pin(map_fd, pin_path))) { + fprintf(stderr, "unable to pin map at %s: %s\n", pin_path, + strerror(errno)); + goto done; + } + + +#define RUN_PING(should_fail, err) if ((ret = run_ping(should_fail, err))) goto done; + + if (!setup_only) { + RUN_PING(false, "Pre-setup ping test"); + + signal(SIGINT, cleanup); + signal(SIGTERM, cleanup); + } + + if ((ret = bpf_set_link_xdp_chain(ifindex, pass_prog_fd, map_fd, xdp_flags)) < 0) { + fprintf(stderr, "Link set xdp fd failed for %s: %s\n", ifname, + strerror(-ret)); + goto done; + } + + if ((ret = bpf_get_link_xdp_chain(ifindex, &prog_id, &chain_map_id, 0)) < 0) { + fprintf(stderr, "Unable to get xdp IDs for %s: '%s'\n", ifname, strerror(-ret)); + goto done; + } + printf(" XDP prog ID: %u Chain map ID: %u\n", prog_id, chain_map_id); + + if (!setup_only) { + sleep(1); + RUN_PING(false, "Empty map test"); + } + + acts.wildcard_act = drop_prog_fd; + if (bpf_map_update_elem(map_fd, &map_key, &acts, 0)) { + fprintf(stderr, "unable to insert into map: %s\n", strerror(errno)); + goto done; + } + + if (setup_only) { + printf("Setup done; exiting.\n"); + ret = 0; + goto done; + } + + sleep(1); + + RUN_PING(true, "Wildcard act test"); + + if (bpf_map_delete_elem(map_fd, &map_key)) { + fprintf(stderr, "unable to delete from map: %s\n", strerror(errno)); + goto done; + } + sleep(1); + + RUN_PING(false, "Post-delete map test"); + + acts.wildcard_act = 0; + acts.pass_act = drop_prog_fd; + if (bpf_map_update_elem(map_fd, &map_key, &acts, 0)) { + fprintf(stderr, "unable to insert into map: %s\n", strerror(errno)); + goto done; + } + sleep(1); + + RUN_PING(true, "Pass act test"); + + + if ((ret = bpf_set_link_xdp_chain(ifindex, -1, -1, xdp_flags)) < 0) { + fprintf(stderr, "Link clear xdp fd failed for %s: '%s'\n", ifname, strerror(-ret)); + goto done; + } + sleep(1); + + RUN_PING(false, "Post-delete prog test"); + + +done: + cleanup(ret); + + if (pass_prog_fd > 0) + close(pass_prog_fd); + if (drop_prog_fd > 0) + close(drop_prog_fd); + if (map_fd > 0) + close(map_fd); + + return ret; +}