diff options
author | Lawrence Brakmo <brakmo@fb.com> | 2018-01-25 19:14:09 -0500 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2018-01-25 19:41:14 -0500 |
commit | de525be2ca2734865d29c4b67ddd29913b214906 (patch) | |
tree | 85e7a4d4b7c45de053c1d9528c1849d65252edfa | |
parent | b73042b8a28e2603ac178295ab96c876ba5a97a1 (diff) |
bpf: Support passing args to sock_ops bpf function
Adds support for passing up to 4 arguments to sock_ops bpf functions. It
reusues the reply union, so the bpf_sock_ops structures are not
increased in size.
Signed-off-by: Lawrence Brakmo <brakmo@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r-- | include/linux/filter.h | 1 | ||||
-rw-r--r-- | include/net/tcp.h | 40 | ||||
-rw-r--r-- | include/uapi/linux/bpf.h | 5 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_nv.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 2 |
6 files changed, 42 insertions, 10 deletions
diff --git a/include/linux/filter.h b/include/linux/filter.h index daa5a676335f..20384c4bed25 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h | |||
@@ -1003,6 +1003,7 @@ struct bpf_sock_ops_kern { | |||
1003 | struct sock *sk; | 1003 | struct sock *sk; |
1004 | u32 op; | 1004 | u32 op; |
1005 | union { | 1005 | union { |
1006 | u32 args[4]; | ||
1006 | u32 reply; | 1007 | u32 reply; |
1007 | u32 replylong[4]; | 1008 | u32 replylong[4]; |
1008 | }; | 1009 | }; |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 6092eaff61cf..093e967a2960 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -2006,7 +2006,7 @@ void tcp_cleanup_ulp(struct sock *sk); | |||
2006 | * program loaded). | 2006 | * program loaded). |
2007 | */ | 2007 | */ |
2008 | #ifdef CONFIG_BPF | 2008 | #ifdef CONFIG_BPF |
2009 | static inline int tcp_call_bpf(struct sock *sk, int op) | 2009 | static inline int tcp_call_bpf(struct sock *sk, int op, u32 nargs, u32 *args) |
2010 | { | 2010 | { |
2011 | struct bpf_sock_ops_kern sock_ops; | 2011 | struct bpf_sock_ops_kern sock_ops; |
2012 | int ret; | 2012 | int ret; |
@@ -2019,6 +2019,8 @@ static inline int tcp_call_bpf(struct sock *sk, int op) | |||
2019 | 2019 | ||
2020 | sock_ops.sk = sk; | 2020 | sock_ops.sk = sk; |
2021 | sock_ops.op = op; | 2021 | sock_ops.op = op; |
2022 | if (nargs > 0) | ||
2023 | memcpy(sock_ops.args, args, nargs * sizeof(*args)); | ||
2022 | 2024 | ||
2023 | ret = BPF_CGROUP_RUN_PROG_SOCK_OPS(&sock_ops); | 2025 | ret = BPF_CGROUP_RUN_PROG_SOCK_OPS(&sock_ops); |
2024 | if (ret == 0) | 2026 | if (ret == 0) |
@@ -2027,18 +2029,46 @@ static inline int tcp_call_bpf(struct sock *sk, int op) | |||
2027 | ret = -1; | 2029 | ret = -1; |
2028 | return ret; | 2030 | return ret; |
2029 | } | 2031 | } |
2032 | |||
2033 | static inline int tcp_call_bpf_2arg(struct sock *sk, int op, u32 arg1, u32 arg2) | ||
2034 | { | ||
2035 | u32 args[2] = {arg1, arg2}; | ||
2036 | |||
2037 | return tcp_call_bpf(sk, op, 2, args); | ||
2038 | } | ||
2039 | |||
2040 | static inline int tcp_call_bpf_3arg(struct sock *sk, int op, u32 arg1, u32 arg2, | ||
2041 | u32 arg3) | ||
2042 | { | ||
2043 | u32 args[3] = {arg1, arg2, arg3}; | ||
2044 | |||
2045 | return tcp_call_bpf(sk, op, 3, args); | ||
2046 | } | ||
2047 | |||
2030 | #else | 2048 | #else |
2031 | static inline int tcp_call_bpf(struct sock *sk, int op) | 2049 | static inline int tcp_call_bpf(struct sock *sk, int op, u32 nargs, u32 *args) |
2032 | { | 2050 | { |
2033 | return -EPERM; | 2051 | return -EPERM; |
2034 | } | 2052 | } |
2053 | |||
2054 | static inline int tcp_call_bpf_2arg(struct sock *sk, int op, u32 arg1, u32 arg2) | ||
2055 | { | ||
2056 | return -EPERM; | ||
2057 | } | ||
2058 | |||
2059 | static inline int tcp_call_bpf_3arg(struct sock *sk, int op, u32 arg1, u32 arg2, | ||
2060 | u32 arg3) | ||
2061 | { | ||
2062 | return -EPERM; | ||
2063 | } | ||
2064 | |||
2035 | #endif | 2065 | #endif |
2036 | 2066 | ||
2037 | static inline u32 tcp_timeout_init(struct sock *sk) | 2067 | static inline u32 tcp_timeout_init(struct sock *sk) |
2038 | { | 2068 | { |
2039 | int timeout; | 2069 | int timeout; |
2040 | 2070 | ||
2041 | timeout = tcp_call_bpf(sk, BPF_SOCK_OPS_TIMEOUT_INIT); | 2071 | timeout = tcp_call_bpf(sk, BPF_SOCK_OPS_TIMEOUT_INIT, 0, NULL); |
2042 | 2072 | ||
2043 | if (timeout <= 0) | 2073 | if (timeout <= 0) |
2044 | timeout = TCP_TIMEOUT_INIT; | 2074 | timeout = TCP_TIMEOUT_INIT; |
@@ -2049,7 +2079,7 @@ static inline u32 tcp_rwnd_init_bpf(struct sock *sk) | |||
2049 | { | 2079 | { |
2050 | int rwnd; | 2080 | int rwnd; |
2051 | 2081 | ||
2052 | rwnd = tcp_call_bpf(sk, BPF_SOCK_OPS_RWND_INIT); | 2082 | rwnd = tcp_call_bpf(sk, BPF_SOCK_OPS_RWND_INIT, 0, NULL); |
2053 | 2083 | ||
2054 | if (rwnd < 0) | 2084 | if (rwnd < 0) |
2055 | rwnd = 0; | 2085 | rwnd = 0; |
@@ -2058,7 +2088,7 @@ static inline u32 tcp_rwnd_init_bpf(struct sock *sk) | |||
2058 | 2088 | ||
2059 | static inline bool tcp_bpf_ca_needs_ecn(struct sock *sk) | 2089 | static inline bool tcp_bpf_ca_needs_ecn(struct sock *sk) |
2060 | { | 2090 | { |
2061 | return (tcp_call_bpf(sk, BPF_SOCK_OPS_NEEDS_ECN) == 1); | 2091 | return (tcp_call_bpf(sk, BPF_SOCK_OPS_NEEDS_ECN, 0, NULL) == 1); |
2062 | } | 2092 | } |
2063 | 2093 | ||
2064 | #if IS_ENABLED(CONFIG_SMC) | 2094 | #if IS_ENABLED(CONFIG_SMC) |
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 406c19d6016b..8d5874c2c4ff 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h | |||
@@ -952,8 +952,9 @@ struct bpf_map_info { | |||
952 | struct bpf_sock_ops { | 952 | struct bpf_sock_ops { |
953 | __u32 op; | 953 | __u32 op; |
954 | union { | 954 | union { |
955 | __u32 reply; | 955 | __u32 args[4]; /* Optionally passed to bpf program */ |
956 | __u32 replylong[4]; | 956 | __u32 reply; /* Returned by bpf program */ |
957 | __u32 replylong[4]; /* Optionally returned by bpf prog */ | ||
957 | }; | 958 | }; |
958 | __u32 family; | 959 | __u32 family; |
959 | __u32 remote_ip4; /* Stored in network byte order */ | 960 | __u32 remote_ip4; /* Stored in network byte order */ |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index d7cf861bf699..88b62441e7e9 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -463,7 +463,7 @@ void tcp_init_transfer(struct sock *sk, int bpf_op) | |||
463 | tcp_mtup_init(sk); | 463 | tcp_mtup_init(sk); |
464 | icsk->icsk_af_ops->rebuild_header(sk); | 464 | icsk->icsk_af_ops->rebuild_header(sk); |
465 | tcp_init_metrics(sk); | 465 | tcp_init_metrics(sk); |
466 | tcp_call_bpf(sk, bpf_op); | 466 | tcp_call_bpf(sk, bpf_op, 0, NULL); |
467 | tcp_init_congestion_control(sk); | 467 | tcp_init_congestion_control(sk); |
468 | tcp_init_buffer_space(sk); | 468 | tcp_init_buffer_space(sk); |
469 | } | 469 | } |
diff --git a/net/ipv4/tcp_nv.c b/net/ipv4/tcp_nv.c index 0b5a05bd82e3..ddbce73edae8 100644 --- a/net/ipv4/tcp_nv.c +++ b/net/ipv4/tcp_nv.c | |||
@@ -146,7 +146,7 @@ static void tcpnv_init(struct sock *sk) | |||
146 | * within a datacenter, where we have reasonable estimates of | 146 | * within a datacenter, where we have reasonable estimates of |
147 | * RTTs | 147 | * RTTs |
148 | */ | 148 | */ |
149 | base_rtt = tcp_call_bpf(sk, BPF_SOCK_OPS_BASE_RTT); | 149 | base_rtt = tcp_call_bpf(sk, BPF_SOCK_OPS_BASE_RTT, 0, NULL); |
150 | if (base_rtt > 0) { | 150 | if (base_rtt > 0) { |
151 | ca->nv_base_rtt = base_rtt; | 151 | ca->nv_base_rtt = base_rtt; |
152 | ca->nv_lower_bound_rtt = (base_rtt * 205) >> 8; /* 80% */ | 152 | ca->nv_lower_bound_rtt = (base_rtt * 205) >> 8; /* 80% */ |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 95461f02ac9a..d12f7f71c1c4 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -3469,7 +3469,7 @@ int tcp_connect(struct sock *sk) | |||
3469 | struct sk_buff *buff; | 3469 | struct sk_buff *buff; |
3470 | int err; | 3470 | int err; |
3471 | 3471 | ||
3472 | tcp_call_bpf(sk, BPF_SOCK_OPS_TCP_CONNECT_CB); | 3472 | tcp_call_bpf(sk, BPF_SOCK_OPS_TCP_CONNECT_CB, 0, NULL); |
3473 | 3473 | ||
3474 | if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk)) | 3474 | if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk)) |
3475 | return -EHOSTUNREACH; /* Routing failure or similar. */ | 3475 | return -EHOSTUNREACH; /* Routing failure or similar. */ |