Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
sudo: required
language: bash
dist: bionic
services:
- docker

env:
global:
- PROJECT_NAME='libbpf'
- AUTHOR_EMAIL="$(git log -1 --pretty=\"%aE\")"
- REPO_ROOT="$TRAVIS_BUILD_DIR"
- CI_ROOT="$REPO_ROOT/travis-ci"
- VMTEST_ROOT="$CI_ROOT/vmtest"

addons:
apt:
packages:
- qemu-kvm
- zstd
- binutils-dev
- elfutils
- libcap-dev
- libelf-dev
- libdw-dev
- python3-docutils

jobs:
include:
- stage: Builds & Tests
name: Kernel LATEST + selftests
language: bash
env: KERNEL=LATEST
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1
1 change: 1 addition & 0 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1914,6 +1914,7 @@ struct sk_reuseport_kern {
u32 hash;
u32 reuseport_id;
bool bind_inany;
u8 migration;
};
bool bpf_tcp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
struct bpf_insn_access_aux *info);
Expand Down
4 changes: 2 additions & 2 deletions include/linux/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -967,12 +967,12 @@ void bpf_warn_invalid_xdp_action(u32 act);
#ifdef CONFIG_INET
struct sock *bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk,
struct bpf_prog *prog, struct sk_buff *skb,
u32 hash);
u32 hash, u8 migration);
#else
static inline struct sock *
bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk,
struct bpf_prog *prog, struct sk_buff *skb,
u32 hash)
u32 hash, u8 migration)
{
return NULL;
}
Expand Down
8 changes: 8 additions & 0 deletions include/linux/spinlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define raw_spin_lock_nested(lock, subclass) \
_raw_spin_lock_nested(lock, subclass)
# define raw_spin_lock_bh_nested(lock, subclass) \
_raw_spin_lock_bh_nested(lock, subclass)

# define raw_spin_lock_nest_lock(lock, nest_lock) \
do { \
Expand All @@ -242,6 +244,7 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
# define raw_spin_lock_nested(lock, subclass) \
_raw_spin_lock(((void)(subclass), (lock)))
# define raw_spin_lock_nest_lock(lock, nest_lock) _raw_spin_lock(lock)
# define raw_spin_lock_bh_nested(lock, subclass) _raw_spin_lock_bh(lock)
#endif

#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
Expand Down Expand Up @@ -369,6 +372,11 @@ do { \
raw_spin_lock_nested(spinlock_check(lock), subclass); \
} while (0)

#define spin_lock_bh_nested(lock, subclass) \
do { \
raw_spin_lock_bh_nested(spinlock_check(lock), subclass);\
} while (0)

#define spin_lock_nest_lock(lock, nest_lock) \
do { \
raw_spin_lock_nest_lock(spinlock_check(lock), nest_lock); \
Expand Down
2 changes: 2 additions & 0 deletions include/linux/spinlock_api_smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ int in_lock_functions(unsigned long addr);
void __lockfunc _raw_spin_lock(raw_spinlock_t *lock) __acquires(lock);
void __lockfunc _raw_spin_lock_nested(raw_spinlock_t *lock, int subclass)
__acquires(lock);
void __lockfunc _raw_spin_lock_bh_nested(raw_spinlock_t *lock, int subclass)
__acquires(lock);
void __lockfunc
_raw_spin_lock_nest_lock(raw_spinlock_t *lock, struct lockdep_map *map)
__acquires(lock);
Expand Down
1 change: 1 addition & 0 deletions include/linux/spinlock_api_up.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@

#define _raw_spin_lock(lock) __LOCK(lock)
#define _raw_spin_lock_nested(lock, subclass) __LOCK(lock)
#define _raw_spin_lock_bh_nested(lock, subclass) __LOCK(lock)
#define _raw_read_lock(lock) __LOCK(lock)
#define _raw_write_lock(lock) __LOCK(lock)
#define _raw_spin_lock_bh(lock) __LOCK_BH(lock)
Expand Down
12 changes: 12 additions & 0 deletions include/net/inet_connection_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
struct sock *inet_csk_reqsk_queue_add(struct sock *sk,
struct request_sock *req,
struct sock *child);
void inet_csk_reqsk_queue_migrate(struct sock *sk, struct sock *nsk);
void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
unsigned long timeout);
struct sock *inet_csk_complete_hashdance(struct sock *sk, struct sock *child,
Expand All @@ -271,6 +272,17 @@ static inline void inet_csk_reqsk_queue_added(struct sock *sk)
reqsk_queue_added(&inet_csk(sk)->icsk_accept_queue);
}

static inline void inet_csk_reqsk_queue_migrated(struct sock *sk,
struct sock *nsk,
struct request_sock *req)
{
reqsk_queue_migrated(&inet_csk(sk)->icsk_accept_queue,
&inet_csk(nsk)->icsk_accept_queue,
req);
sock_put(sk);
req->rsk_listener = nsk;
}

static inline int inet_csk_reqsk_queue_len(const struct sock *sk)
{
return reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue);
Expand Down
13 changes: 13 additions & 0 deletions include/net/request_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,19 @@ static inline void reqsk_queue_added(struct request_sock_queue *queue)
atomic_inc(&queue->qlen);
}

static inline void reqsk_queue_migrated(struct request_sock_queue *old_accept_queue,
struct request_sock_queue *new_accept_queue,
const struct request_sock *req)
{
atomic_dec(&old_accept_queue->qlen);
atomic_inc(&new_accept_queue->qlen);

if (req->num_timeout == 0) {
atomic_dec(&old_accept_queue->young);
atomic_inc(&new_accept_queue->young);
}
}

static inline int reqsk_queue_len(const struct request_sock_queue *queue)
{
return atomic_read(&queue->qlen);
Expand Down
15 changes: 8 additions & 7 deletions include/net/sock_reuseport.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ extern spinlock_t reuseport_lock;
struct sock_reuseport {
struct rcu_head rcu;

u16 max_socks; /* length of socks */
u16 num_socks; /* elements in socks */
u16 max_socks; /* length of socks */
u16 num_socks; /* elements in socks */
u16 num_closed_socks; /* closed elements in socks */
/* The last synq overflow event timestamp of this
* reuse->socks[] group.
*/
Expand All @@ -30,11 +31,11 @@ struct sock_reuseport {
extern int reuseport_alloc(struct sock *sk, bool bind_inany);
extern int reuseport_add_sock(struct sock *sk, struct sock *sk2,
bool bind_inany);
extern void reuseport_detach_sock(struct sock *sk);
extern struct sock *reuseport_select_sock(struct sock *sk,
u32 hash,
struct sk_buff *skb,
int hdr_len);
extern struct sock *reuseport_detach_sock(struct sock *sk);
extern struct sock *reuseport_select_sock(struct sock *sk, u32 hash,
struct sk_buff *skb, int hdr_len);
extern struct sock *reuseport_select_migrated_sock(struct sock *sk, u32 hash,
struct sk_buff *skb);
extern int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog);
extern int reuseport_detach_prog(struct sock *sk);

Expand Down
25 changes: 25 additions & 0 deletions include/uapi/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ enum bpf_attach_type {
BPF_XDP_CPUMAP,
BPF_SK_LOOKUP,
BPF_XDP,
BPF_SK_REUSEPORT_SELECT,
BPF_SK_REUSEPORT_SELECT_OR_MIGRATE,
__MAX_BPF_ATTACH_TYPE
};

Expand Down Expand Up @@ -1653,6 +1655,13 @@ union bpf_attr {
* A 8-byte long non-decreasing number on success, or 0 if the
* socket field is missing inside *skb*.
*
* u64 bpf_get_socket_cookie(struct bpf_sock *sk)
* Description
* Equivalent to bpf_get_socket_cookie() helper that accepts
* *skb*, but gets socket from **struct bpf_sock** context.
* Return
* A 8-byte long non-decreasing number.
*
* u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx)
* Description
* Equivalent to bpf_get_socket_cookie() helper that accepts
Expand Down Expand Up @@ -4432,6 +4441,20 @@ struct sk_msg_md {
__bpf_md_ptr(struct bpf_sock *, sk); /* current socket */
};

/* Migration type for SO_REUSEPORT enabled TCP sockets.
*
* BPF_SK_REUSEPORT_MIGRATE_NO : Select a listener for SYN packets.
* BPF_SK_REUSEPORT_MIGRATE_QUEUE : Migrate ESTABLISHED and SYN_RECV sockets in
* the accept queue at close() or shutdown().
* BPF_SK_REUSEPORT_MIGRATE_REQUEST : Migrate NEW_SYN_RECV socket at receiving the
* final ACK of 3WHS or retransmitting SYN+ACKs.
*/
enum {
BPF_SK_REUSEPORT_MIGRATE_NO,
BPF_SK_REUSEPORT_MIGRATE_QUEUE,
BPF_SK_REUSEPORT_MIGRATE_REQUEST,
};

struct sk_reuseport_md {
/*
* Start of directly accessible data. It begins from
Expand All @@ -4455,6 +4478,8 @@ struct sk_reuseport_md {
__u32 ip_protocol; /* IP protocol. e.g. IPPROTO_TCP, IPPROTO_UDP */
__u32 bind_inany; /* Is sock bound to an INANY address? */
__u32 hash; /* A hash of the packet 4 tuples */
__u8 migration; /* Migration type */
__bpf_md_ptr(struct bpf_sock *, sk); /* Current listening socket */
};

#define BPF_TAG_SIZE 8
Expand Down
13 changes: 13 additions & 0 deletions kernel/bpf/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,11 @@ static void bpf_prog_load_fixup_attach_type(union bpf_attr *attr)
attr->expected_attach_type =
BPF_CGROUP_INET_SOCK_CREATE;
break;
case BPF_PROG_TYPE_SK_REUSEPORT:
if (!attr->expected_attach_type)
attr->expected_attach_type =
BPF_SK_REUSEPORT_SELECT;
break;
}
}

Expand Down Expand Up @@ -2003,6 +2008,14 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
if (expected_attach_type == BPF_SK_LOOKUP)
return 0;
return -EINVAL;
case BPF_PROG_TYPE_SK_REUSEPORT:
switch (expected_attach_type) {
case BPF_SK_REUSEPORT_SELECT:
case BPF_SK_REUSEPORT_SELECT_OR_MIGRATE:
return 0;
default:
return -EINVAL;
}
case BPF_PROG_TYPE_EXT:
if (expected_attach_type)
return -EINVAL;
Expand Down
8 changes: 8 additions & 0 deletions kernel/locking/spinlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,14 @@ void __lockfunc _raw_spin_lock_nested(raw_spinlock_t *lock, int subclass)
}
EXPORT_SYMBOL(_raw_spin_lock_nested);

void __lockfunc _raw_spin_lock_bh_nested(raw_spinlock_t *lock, int subclass)
{
__local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}
EXPORT_SYMBOL(_raw_spin_lock_bh_nested);

unsigned long __lockfunc _raw_spin_lock_irqsave_nested(raw_spinlock_t *lock,
int subclass)
{
Expand Down
56 changes: 53 additions & 3 deletions net/core/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -4631,6 +4631,18 @@ static const struct bpf_func_proto bpf_get_socket_cookie_sock_proto = {
.arg1_type = ARG_PTR_TO_CTX,
};

BPF_CALL_1(bpf_get_socket_pointer_cookie, struct sock *, sk)
{
return __sock_gen_cookie(sk);
}

static const struct bpf_func_proto bpf_get_socket_pointer_cookie_proto = {
.func = bpf_get_socket_pointer_cookie,
.gpl_only = false,
.ret_type = RET_INTEGER,
.arg1_type = ARG_PTR_TO_SOCKET,
};

BPF_CALL_1(bpf_get_socket_cookie_sock_ops, struct bpf_sock_ops_kern *, ctx)
{
return __sock_gen_cookie(ctx->sk);
Expand Down Expand Up @@ -9860,7 +9872,7 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
static void bpf_init_reuseport_kern(struct sk_reuseport_kern *reuse_kern,
struct sock_reuseport *reuse,
struct sock *sk, struct sk_buff *skb,
u32 hash)
u32 hash, u8 migration)
{
reuse_kern->skb = skb;
reuse_kern->sk = sk;
Expand All @@ -9869,18 +9881,38 @@ static void bpf_init_reuseport_kern(struct sk_reuseport_kern *reuse_kern,
reuse_kern->hash = hash;
reuse_kern->reuseport_id = reuse->reuseport_id;
reuse_kern->bind_inany = reuse->bind_inany;
reuse_kern->migration = migration;
}

struct sock *bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk,
struct bpf_prog *prog, struct sk_buff *skb,
u32 hash)
u32 hash, u8 migration)
{
struct sk_reuseport_kern reuse_kern;
enum sk_action action;
bool allocated = false;

if (migration) {
/* cancel migration for possibly incapable eBPF program */
if (prog->expected_attach_type != BPF_SK_REUSEPORT_SELECT_OR_MIGRATE)
return ERR_PTR(-ENOTSUPP);

if (!skb) {
allocated = true;
skb = alloc_skb(0, GFP_ATOMIC);
if (!skb)
return ERR_PTR(-ENOMEM);
}
} else if (!skb) {
return NULL; /* fall back to select by hash */
}

bpf_init_reuseport_kern(&reuse_kern, reuse, sk, skb, hash);
bpf_init_reuseport_kern(&reuse_kern, reuse, sk, skb, hash, migration);
action = BPF_PROG_RUN(prog, &reuse_kern);

if (allocated)
kfree_skb(skb);

if (action == SK_PASS)
return reuse_kern.selected_sk;
else
Expand Down Expand Up @@ -9988,6 +10020,8 @@ sk_reuseport_func_proto(enum bpf_func_id func_id,
return &sk_reuseport_load_bytes_proto;
case BPF_FUNC_skb_load_bytes_relative:
return &sk_reuseport_load_bytes_relative_proto;
case BPF_FUNC_get_socket_cookie:
return &bpf_get_socket_pointer_cookie_proto;
default:
return bpf_base_func_proto(func_id);
}
Expand Down Expand Up @@ -10017,6 +10051,14 @@ sk_reuseport_is_valid_access(int off, int size,
case offsetof(struct sk_reuseport_md, hash):
return size == size_default;

case bpf_ctx_range(struct sk_reuseport_md, migration):
return prog->expected_attach_type == BPF_SK_REUSEPORT_SELECT_OR_MIGRATE &&
size == sizeof(__u8);

case offsetof(struct sk_reuseport_md, sk):
info->reg_type = PTR_TO_SOCKET;
return size == sizeof(__u64);

/* Fields that allow narrowing */
case bpf_ctx_range(struct sk_reuseport_md, eth_protocol):
if (size < sizeof_field(struct sk_buff, protocol))
Expand Down Expand Up @@ -10089,6 +10131,14 @@ static u32 sk_reuseport_convert_ctx_access(enum bpf_access_type type,
case offsetof(struct sk_reuseport_md, bind_inany):
SK_REUSEPORT_LOAD_FIELD(bind_inany);
break;

case offsetof(struct sk_reuseport_md, migration):
SK_REUSEPORT_LOAD_FIELD(migration);
break;

case offsetof(struct sk_reuseport_md, sk):
SK_REUSEPORT_LOAD_FIELD(sk);
break;
}

return insn - insn_buf;
Expand Down
Loading