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
15 changes: 15 additions & 0 deletions Documentation/networking/ip-sysctl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,21 @@ tcp_syncookies - INTEGER
network connections you can set this knob to 2 to enable
unconditionally generation of syncookies.

tcp_migrate_req - INTEGER
By default, when a listening socket is closed, child sockets are also
closed. If it has SO_REUSEPORT enabled, the dropped connections should
have been accepted by other listeners on the same port. This option
makes it possible to migrate child sockets to another listener when
calling close() or shutdown().

Default: 0

Note that the source and destination listeners _must_ have the same
settings at the socket API level. If there are different kinds of
sockets on the port, disable this option or use
BPF_PROG_TYPE_SK_REUSEPORT program to select the correct socket by
bpf_sk_select_reuseport() or to cancel migration by returning SK_DROP.

tcp_fastopen - INTEGER
Enable TCP Fast Open (RFC7413) to send and accept data in the opening
SYN packet.
Expand Down
1 change: 1 addition & 0 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1897,6 +1897,7 @@ struct sk_reuseport_kern {
u32 hash;
u32 reuseport_id;
bool bind_inany;
u64 cookie;
};
bool bpf_tcp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
struct bpf_insn_access_aux *info);
Expand Down
13 changes: 13 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,18 @@ 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);
sock_hold(nsk);
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
1 change: 1 addition & 0 deletions include/net/netns/ipv4.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ struct netns_ipv4 {
int sysctl_tcp_syn_retries;
int sysctl_tcp_synack_retries;
int sysctl_tcp_syncookies;
int sysctl_tcp_migrate_req;
int sysctl_tcp_reordering;
int sysctl_tcp_retries1;
int sysctl_tcp_retries2;
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
8 changes: 5 additions & 3 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 @@ -23,14 +24,15 @@ struct sock_reuseport {
unsigned int reuseport_id;
unsigned int bind_inany:1;
unsigned int has_conns:1;
unsigned int migrate_req:1;
struct bpf_prog __rcu *prog; /* optional BPF sock selector */
struct sock *socks[]; /* array of sock pointers */
};

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_detach_sock(struct sock *sk);
extern struct sock *reuseport_select_sock(struct sock *sk,
u32 hash,
struct sk_buff *skb,
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -4403,6 +4403,7 @@ 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 */
__u64 cookie; /* ID of the listener in map */
};

#define BPF_TAG_SIZE 8
Expand Down
34 changes: 29 additions & 5 deletions net/core/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -8914,6 +8914,22 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF(S, NS, F, NF, \
BPF_FIELD_SIZEOF(NS, NF), 0)

#define SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF_OR_NULL(S, NS, F, NF, SIZE, OFF) \
do { \
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(S, F), si->dst_reg, \
si->src_reg, offsetof(S, F)); \
*insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 1); \
*insn++ = BPF_LDX_MEM( \
SIZE, si->dst_reg, si->dst_reg, \
bpf_target_off(NS, NF, sizeof_field(NS, NF), \
target_size) \
+ OFF); \
} while (0)

#define SOCK_ADDR_LOAD_NESTED_FIELD_OR_NULL(S, NS, F, NF) \
SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF_OR_NULL(S, NS, F, NF, \
BPF_FIELD_SIZEOF(NS, NF), 0)

/* SOCK_ADDR_STORE_NESTED_FIELD_OFF() has semantic similar to
* SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF() but for store operation.
*
Expand Down Expand Up @@ -9858,10 +9874,11 @@ static void bpf_init_reuseport_kern(struct sk_reuseport_kern *reuse_kern,
reuse_kern->skb = skb;
reuse_kern->sk = sk;
reuse_kern->selected_sk = NULL;
reuse_kern->data_end = skb->data + skb_headlen(skb);
reuse_kern->data_end = skb ? skb->data + skb_headlen(skb) : NULL;
reuse_kern->hash = hash;
reuse_kern->reuseport_id = reuse->reuseport_id;
reuse_kern->bind_inany = reuse->bind_inany;
reuse_kern->cookie = sock_gen_cookie(sk);
}

struct sock *bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk,
Expand Down Expand Up @@ -10010,6 +10027,9 @@ 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, cookie):
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 All @@ -10035,10 +10055,10 @@ sk_reuseport_is_valid_access(int off, int size,
})

#define SK_REUSEPORT_LOAD_SKB_FIELD(SKB_FIELD) \
SOCK_ADDR_LOAD_NESTED_FIELD(struct sk_reuseport_kern, \
struct sk_buff, \
skb, \
SKB_FIELD)
SOCK_ADDR_LOAD_NESTED_FIELD_OR_NULL(struct sk_reuseport_kern, \
struct sk_buff, \
skb, \
SKB_FIELD)

#define SK_REUSEPORT_LOAD_SK_FIELD(SK_FIELD) \
SOCK_ADDR_LOAD_NESTED_FIELD(struct sk_reuseport_kern, \
Expand Down Expand Up @@ -10082,6 +10102,10 @@ 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, cookie):
SK_REUSEPORT_LOAD_FIELD(cookie);
break;
}

return insn - insn_buf;
Expand Down
Loading