Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Daniel Borkmann says: ==================== pull-request: bpf-next 2019-05-06 The following pull-request contains BPF updates for your *net-next* tree. The main changes are: 1) Two AF_XDP libbpf fixes for socket teardown; first one an invalid munmap and the other one an invalid skmap cleanup, both from Björn. 2) More graceful CONFIG_DEBUG_INFO_BTF handling when pahole is not present in the system to generate vmlinux btf info, from Andrii. 3) Fix libbpf and thus fix perf build error with uClibc on arc architecture, from Vineet. 4) Fix missing libbpf_util.h header install in libbpf, from William. 5) Exclude bash-completion/bpftool from .gitignore pattern, from Masahiro. 6) Fix up rlimit in test_libbpf_open kselftest test case, from Yonghong. 7) Minor misc cleanups. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
14cfbdac66
|
@ -708,7 +708,7 @@ static int bpf_fd_sk_storage_update_elem(struct bpf_map *map, void *key,
|
||||||
if (sock) {
|
if (sock) {
|
||||||
sdata = sk_storage_update(sock->sk, map, value, map_flags);
|
sdata = sk_storage_update(sock->sk, map, value, map_flags);
|
||||||
sockfd_put(sock);
|
sockfd_put(sock);
|
||||||
return IS_ERR(sdata) ? PTR_ERR(sdata) : 0;
|
return PTR_ERR_OR_ZERO(sdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -96,6 +96,11 @@ gen_btf()
|
||||||
{
|
{
|
||||||
local pahole_ver;
|
local pahole_ver;
|
||||||
|
|
||||||
|
if ! [ -x "$(command -v ${PAHOLE})" ]; then
|
||||||
|
info "BTF" "${1}: pahole (${PAHOLE}) is not available"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
|
pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
|
||||||
if [ "${pahole_ver}" -lt "113" ]; then
|
if [ "${pahole_ver}" -lt "113" ]; then
|
||||||
info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
|
info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
*.d
|
*.d
|
||||||
bpftool
|
/bpftool
|
||||||
bpftool*.8
|
bpftool*.8
|
||||||
bpf-helpers.*
|
bpf-helpers.*
|
||||||
FEATURE-DUMP.bpftool
|
FEATURE-DUMP.bpftool
|
||||||
|
|
|
@ -230,6 +230,7 @@ install_headers:
|
||||||
$(call do_install,bpf.h,$(prefix)/include/bpf,644); \
|
$(call do_install,bpf.h,$(prefix)/include/bpf,644); \
|
||||||
$(call do_install,libbpf.h,$(prefix)/include/bpf,644); \
|
$(call do_install,libbpf.h,$(prefix)/include/bpf,644); \
|
||||||
$(call do_install,btf.h,$(prefix)/include/bpf,644); \
|
$(call do_install,btf.h,$(prefix)/include/bpf,644); \
|
||||||
|
$(call do_install,libbpf_util.h,$(prefix)/include/bpf,644); \
|
||||||
$(call do_install,xsk.h,$(prefix)/include/bpf,644);
|
$(call do_install,xsk.h,$(prefix)/include/bpf,644);
|
||||||
|
|
||||||
install_pkgconfig: $(PC_FILE)
|
install_pkgconfig: $(PC_FILE)
|
||||||
|
|
|
@ -46,6 +46,8 @@
|
||||||
# define __NR_bpf 349
|
# define __NR_bpf 349
|
||||||
# elif defined(__s390__)
|
# elif defined(__s390__)
|
||||||
# define __NR_bpf 351
|
# define __NR_bpf 351
|
||||||
|
# elif defined(__arc__)
|
||||||
|
# define __NR_bpf 280
|
||||||
# else
|
# else
|
||||||
# error __NR_bpf not defined. libbpf does not support your arch.
|
# error __NR_bpf not defined. libbpf does not support your arch.
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -248,8 +248,7 @@ int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_mmap:
|
out_mmap:
|
||||||
munmap(umem->fill,
|
munmap(map, off.fr.desc + umem->config.fill_size * sizeof(__u64));
|
||||||
off.fr.desc + umem->config.fill_size * sizeof(__u64));
|
|
||||||
out_socket:
|
out_socket:
|
||||||
close(umem->fd);
|
close(umem->fd);
|
||||||
out_umem_alloc:
|
out_umem_alloc:
|
||||||
|
@ -388,21 +387,17 @@ static void xsk_delete_bpf_maps(struct xsk_socket *xsk)
|
||||||
{
|
{
|
||||||
close(xsk->qidconf_map_fd);
|
close(xsk->qidconf_map_fd);
|
||||||
close(xsk->xsks_map_fd);
|
close(xsk->xsks_map_fd);
|
||||||
|
xsk->qidconf_map_fd = -1;
|
||||||
|
xsk->xsks_map_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xsk_update_bpf_maps(struct xsk_socket *xsk, int qidconf_value,
|
static int xsk_lookup_bpf_maps(struct xsk_socket *xsk)
|
||||||
int xsks_value)
|
|
||||||
{
|
{
|
||||||
bool qidconf_map_updated = false, xsks_map_updated = false;
|
__u32 i, *map_ids, num_maps, prog_len = sizeof(struct bpf_prog_info);
|
||||||
|
__u32 map_len = sizeof(struct bpf_map_info);
|
||||||
struct bpf_prog_info prog_info = {};
|
struct bpf_prog_info prog_info = {};
|
||||||
__u32 prog_len = sizeof(prog_info);
|
|
||||||
struct bpf_map_info map_info;
|
struct bpf_map_info map_info;
|
||||||
__u32 map_len = sizeof(map_info);
|
int fd, err;
|
||||||
__u32 *map_ids;
|
|
||||||
int reset_value = 0;
|
|
||||||
__u32 num_maps;
|
|
||||||
unsigned int i;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = bpf_obj_get_info_by_fd(xsk->prog_fd, &prog_info, &prog_len);
|
err = bpf_obj_get_info_by_fd(xsk->prog_fd, &prog_info, &prog_len);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -423,66 +418,71 @@ static int xsk_update_bpf_maps(struct xsk_socket *xsk, int qidconf_value,
|
||||||
goto out_map_ids;
|
goto out_map_ids;
|
||||||
|
|
||||||
for (i = 0; i < prog_info.nr_map_ids; i++) {
|
for (i = 0; i < prog_info.nr_map_ids; i++) {
|
||||||
int fd;
|
if (xsk->qidconf_map_fd != -1 && xsk->xsks_map_fd != -1)
|
||||||
|
break;
|
||||||
|
|
||||||
fd = bpf_map_get_fd_by_id(map_ids[i]);
|
fd = bpf_map_get_fd_by_id(map_ids[i]);
|
||||||
if (fd < 0) {
|
if (fd < 0)
|
||||||
err = -errno;
|
continue;
|
||||||
goto out_maps;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = bpf_obj_get_info_by_fd(fd, &map_info, &map_len);
|
err = bpf_obj_get_info_by_fd(fd, &map_info, &map_len);
|
||||||
if (err)
|
if (err) {
|
||||||
goto out_maps;
|
close(fd);
|
||||||
|
continue;
|
||||||
if (!strcmp(map_info.name, "qidconf_map")) {
|
|
||||||
err = bpf_map_update_elem(fd, &xsk->queue_id,
|
|
||||||
&qidconf_value, 0);
|
|
||||||
if (err)
|
|
||||||
goto out_maps;
|
|
||||||
qidconf_map_updated = true;
|
|
||||||
xsk->qidconf_map_fd = fd;
|
|
||||||
} else if (!strcmp(map_info.name, "xsks_map")) {
|
|
||||||
err = bpf_map_update_elem(fd, &xsk->queue_id,
|
|
||||||
&xsks_value, 0);
|
|
||||||
if (err)
|
|
||||||
goto out_maps;
|
|
||||||
xsks_map_updated = true;
|
|
||||||
xsk->xsks_map_fd = fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qidconf_map_updated && xsks_map_updated)
|
if (!strcmp(map_info.name, "qidconf_map")) {
|
||||||
break;
|
xsk->qidconf_map_fd = fd;
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(qidconf_map_updated && xsks_map_updated)) {
|
if (!strcmp(map_info.name, "xsks_map")) {
|
||||||
err = -ENOENT;
|
xsk->xsks_map_fd = fd;
|
||||||
goto out_maps;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
goto out_success;
|
if (xsk->qidconf_map_fd < 0 || xsk->xsks_map_fd < 0) {
|
||||||
|
err = -ENOENT;
|
||||||
|
xsk_delete_bpf_maps(xsk);
|
||||||
|
}
|
||||||
|
|
||||||
out_maps:
|
|
||||||
if (qidconf_map_updated)
|
|
||||||
(void)bpf_map_update_elem(xsk->qidconf_map_fd, &xsk->queue_id,
|
|
||||||
&reset_value, 0);
|
|
||||||
if (xsks_map_updated)
|
|
||||||
(void)bpf_map_update_elem(xsk->xsks_map_fd, &xsk->queue_id,
|
|
||||||
&reset_value, 0);
|
|
||||||
out_success:
|
|
||||||
if (qidconf_map_updated)
|
|
||||||
close(xsk->qidconf_map_fd);
|
|
||||||
if (xsks_map_updated)
|
|
||||||
close(xsk->xsks_map_fd);
|
|
||||||
out_map_ids:
|
out_map_ids:
|
||||||
free(map_ids);
|
free(map_ids);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xsk_clear_bpf_maps(struct xsk_socket *xsk)
|
||||||
|
{
|
||||||
|
int qid = false;
|
||||||
|
|
||||||
|
bpf_map_update_elem(xsk->qidconf_map_fd, &xsk->queue_id, &qid, 0);
|
||||||
|
bpf_map_delete_elem(xsk->xsks_map_fd, &xsk->queue_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xsk_set_bpf_maps(struct xsk_socket *xsk)
|
||||||
|
{
|
||||||
|
int qid = true, fd = xsk->fd, err;
|
||||||
|
|
||||||
|
err = bpf_map_update_elem(xsk->qidconf_map_fd, &xsk->queue_id, &qid, 0);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
err = bpf_map_update_elem(xsk->xsks_map_fd, &xsk->queue_id, &fd, 0);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
xsk_clear_bpf_maps(xsk);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int xsk_setup_xdp_prog(struct xsk_socket *xsk)
|
static int xsk_setup_xdp_prog(struct xsk_socket *xsk)
|
||||||
{
|
{
|
||||||
bool prog_attached = false;
|
|
||||||
__u32 prog_id = 0;
|
__u32 prog_id = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -492,7 +492,6 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (!prog_id) {
|
if (!prog_id) {
|
||||||
prog_attached = true;
|
|
||||||
err = xsk_create_bpf_maps(xsk);
|
err = xsk_create_bpf_maps(xsk);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -502,20 +501,21 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk)
|
||||||
goto out_maps;
|
goto out_maps;
|
||||||
} else {
|
} else {
|
||||||
xsk->prog_fd = bpf_prog_get_fd_by_id(prog_id);
|
xsk->prog_fd = bpf_prog_get_fd_by_id(prog_id);
|
||||||
|
err = xsk_lookup_bpf_maps(xsk);
|
||||||
|
if (err)
|
||||||
|
goto out_load;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = xsk_update_bpf_maps(xsk, true, xsk->fd);
|
err = xsk_set_bpf_maps(xsk);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_load;
|
goto out_load;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_load:
|
out_load:
|
||||||
if (prog_attached)
|
close(xsk->prog_fd);
|
||||||
close(xsk->prog_fd);
|
|
||||||
out_maps:
|
out_maps:
|
||||||
if (prog_attached)
|
xsk_delete_bpf_maps(xsk);
|
||||||
xsk_delete_bpf_maps(xsk);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,11 +524,11 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||||
struct xsk_ring_cons *rx, struct xsk_ring_prod *tx,
|
struct xsk_ring_cons *rx, struct xsk_ring_prod *tx,
|
||||||
const struct xsk_socket_config *usr_config)
|
const struct xsk_socket_config *usr_config)
|
||||||
{
|
{
|
||||||
|
void *rx_map = NULL, *tx_map = NULL;
|
||||||
struct sockaddr_xdp sxdp = {};
|
struct sockaddr_xdp sxdp = {};
|
||||||
struct xdp_mmap_offsets off;
|
struct xdp_mmap_offsets off;
|
||||||
struct xsk_socket *xsk;
|
struct xsk_socket *xsk;
|
||||||
socklen_t optlen;
|
socklen_t optlen;
|
||||||
void *map;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!umem || !xsk_ptr || !rx || !tx)
|
if (!umem || !xsk_ptr || !rx || !tx)
|
||||||
|
@ -594,40 +594,40 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx) {
|
if (rx) {
|
||||||
map = xsk_mmap(NULL, off.rx.desc +
|
rx_map = xsk_mmap(NULL, off.rx.desc +
|
||||||
xsk->config.rx_size * sizeof(struct xdp_desc),
|
xsk->config.rx_size * sizeof(struct xdp_desc),
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED | MAP_POPULATE,
|
MAP_SHARED | MAP_POPULATE,
|
||||||
xsk->fd, XDP_PGOFF_RX_RING);
|
xsk->fd, XDP_PGOFF_RX_RING);
|
||||||
if (map == MAP_FAILED) {
|
if (rx_map == MAP_FAILED) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
goto out_socket;
|
goto out_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
rx->mask = xsk->config.rx_size - 1;
|
rx->mask = xsk->config.rx_size - 1;
|
||||||
rx->size = xsk->config.rx_size;
|
rx->size = xsk->config.rx_size;
|
||||||
rx->producer = map + off.rx.producer;
|
rx->producer = rx_map + off.rx.producer;
|
||||||
rx->consumer = map + off.rx.consumer;
|
rx->consumer = rx_map + off.rx.consumer;
|
||||||
rx->ring = map + off.rx.desc;
|
rx->ring = rx_map + off.rx.desc;
|
||||||
}
|
}
|
||||||
xsk->rx = rx;
|
xsk->rx = rx;
|
||||||
|
|
||||||
if (tx) {
|
if (tx) {
|
||||||
map = xsk_mmap(NULL, off.tx.desc +
|
tx_map = xsk_mmap(NULL, off.tx.desc +
|
||||||
xsk->config.tx_size * sizeof(struct xdp_desc),
|
xsk->config.tx_size * sizeof(struct xdp_desc),
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED | MAP_POPULATE,
|
MAP_SHARED | MAP_POPULATE,
|
||||||
xsk->fd, XDP_PGOFF_TX_RING);
|
xsk->fd, XDP_PGOFF_TX_RING);
|
||||||
if (map == MAP_FAILED) {
|
if (tx_map == MAP_FAILED) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
goto out_mmap_rx;
|
goto out_mmap_rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx->mask = xsk->config.tx_size - 1;
|
tx->mask = xsk->config.tx_size - 1;
|
||||||
tx->size = xsk->config.tx_size;
|
tx->size = xsk->config.tx_size;
|
||||||
tx->producer = map + off.tx.producer;
|
tx->producer = tx_map + off.tx.producer;
|
||||||
tx->consumer = map + off.tx.consumer;
|
tx->consumer = tx_map + off.tx.consumer;
|
||||||
tx->ring = map + off.tx.desc;
|
tx->ring = tx_map + off.tx.desc;
|
||||||
tx->cached_cons = xsk->config.tx_size;
|
tx->cached_cons = xsk->config.tx_size;
|
||||||
}
|
}
|
||||||
xsk->tx = tx;
|
xsk->tx = tx;
|
||||||
|
@ -643,6 +643,9 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||||
goto out_mmap_tx;
|
goto out_mmap_tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xsk->qidconf_map_fd = -1;
|
||||||
|
xsk->xsks_map_fd = -1;
|
||||||
|
|
||||||
if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
|
if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
|
||||||
err = xsk_setup_xdp_prog(xsk);
|
err = xsk_setup_xdp_prog(xsk);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -654,13 +657,11 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||||
|
|
||||||
out_mmap_tx:
|
out_mmap_tx:
|
||||||
if (tx)
|
if (tx)
|
||||||
munmap(xsk->tx,
|
munmap(tx_map, off.tx.desc +
|
||||||
off.tx.desc +
|
|
||||||
xsk->config.tx_size * sizeof(struct xdp_desc));
|
xsk->config.tx_size * sizeof(struct xdp_desc));
|
||||||
out_mmap_rx:
|
out_mmap_rx:
|
||||||
if (rx)
|
if (rx)
|
||||||
munmap(xsk->rx,
|
munmap(rx_map, off.rx.desc +
|
||||||
off.rx.desc +
|
|
||||||
xsk->config.rx_size * sizeof(struct xdp_desc));
|
xsk->config.rx_size * sizeof(struct xdp_desc));
|
||||||
out_socket:
|
out_socket:
|
||||||
if (--umem->refcount)
|
if (--umem->refcount)
|
||||||
|
@ -685,9 +686,9 @@ int xsk_umem__delete(struct xsk_umem *umem)
|
||||||
optlen = sizeof(off);
|
optlen = sizeof(off);
|
||||||
err = getsockopt(umem->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen);
|
err = getsockopt(umem->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
munmap(umem->fill->ring,
|
munmap(umem->fill->ring - off.fr.desc,
|
||||||
off.fr.desc + umem->config.fill_size * sizeof(__u64));
|
off.fr.desc + umem->config.fill_size * sizeof(__u64));
|
||||||
munmap(umem->comp->ring,
|
munmap(umem->comp->ring - off.cr.desc,
|
||||||
off.cr.desc + umem->config.comp_size * sizeof(__u64));
|
off.cr.desc + umem->config.comp_size * sizeof(__u64));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,6 +700,7 @@ int xsk_umem__delete(struct xsk_umem *umem)
|
||||||
|
|
||||||
void xsk_socket__delete(struct xsk_socket *xsk)
|
void xsk_socket__delete(struct xsk_socket *xsk)
|
||||||
{
|
{
|
||||||
|
size_t desc_sz = sizeof(struct xdp_desc);
|
||||||
struct xdp_mmap_offsets off;
|
struct xdp_mmap_offsets off;
|
||||||
socklen_t optlen;
|
socklen_t optlen;
|
||||||
int err;
|
int err;
|
||||||
|
@ -706,19 +708,21 @@ void xsk_socket__delete(struct xsk_socket *xsk)
|
||||||
if (!xsk)
|
if (!xsk)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
(void)xsk_update_bpf_maps(xsk, 0, 0);
|
xsk_clear_bpf_maps(xsk);
|
||||||
|
xsk_delete_bpf_maps(xsk);
|
||||||
|
|
||||||
optlen = sizeof(off);
|
optlen = sizeof(off);
|
||||||
err = getsockopt(xsk->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen);
|
err = getsockopt(xsk->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (xsk->rx)
|
if (xsk->rx) {
|
||||||
munmap(xsk->rx->ring,
|
munmap(xsk->rx->ring - off.rx.desc,
|
||||||
off.rx.desc +
|
off.rx.desc + xsk->config.rx_size * desc_sz);
|
||||||
xsk->config.rx_size * sizeof(struct xdp_desc));
|
}
|
||||||
if (xsk->tx)
|
if (xsk->tx) {
|
||||||
munmap(xsk->tx->ring,
|
munmap(xsk->tx->ring - off.tx.desc,
|
||||||
off.tx.desc +
|
off.tx.desc + xsk->config.tx_size * desc_sz);
|
||||||
xsk->config.tx_size * sizeof(struct xdp_desc));
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xsk->umem->refcount--;
|
xsk->umem->refcount--;
|
||||||
|
|
|
@ -11,6 +11,8 @@ static const char *__doc__ =
|
||||||
#include <bpf/libbpf.h>
|
#include <bpf/libbpf.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include "bpf_rlimit.h"
|
||||||
|
|
||||||
static const struct option long_options[] = {
|
static const struct option long_options[] = {
|
||||||
{"help", no_argument, NULL, 'h' },
|
{"help", no_argument, NULL, 'h' },
|
||||||
{"debug", no_argument, NULL, 'D' },
|
{"debug", no_argument, NULL, 'D' },
|
||||||
|
|
Loading…
Reference in New Issue