aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLawrence Brakmo <brakmo@fb.com>2018-01-25 19:14:13 -0500
committerAlexei Starovoitov <ast@kernel.org>2018-01-25 19:41:14 -0500
commit6f9bd3d731aac0d2ac21dd78a642af5df38fb5c5 (patch)
treedf671f4091e123537da0639e818023b109d6bc22 /net
parent44f0e43037d3a17b043843ba67610ac7c7e37db6 (diff)
bpf: Add sock_ops R/W access to tclass
Adds direct write access to sk_txhash and access to tclass for ipv6 flows through getsockopt and setsockopt. Sample usage for tclass: bpf_getsockopt(skops, SOL_IPV6, IPV6_TCLASS, &v, sizeof(v)) where skops is a pointer to the ctx (struct bpf_sock_ops). Signed-off-by: Lawrence Brakmo <brakmo@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index a858ebc4ece4..fe2c7937351f 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3232,6 +3232,29 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
3232 ret = -EINVAL; 3232 ret = -EINVAL;
3233 } 3233 }
3234#ifdef CONFIG_INET 3234#ifdef CONFIG_INET
3235#if IS_ENABLED(CONFIG_IPV6)
3236 } else if (level == SOL_IPV6) {
3237 if (optlen != sizeof(int) || sk->sk_family != AF_INET6)
3238 return -EINVAL;
3239
3240 val = *((int *)optval);
3241 /* Only some options are supported */
3242 switch (optname) {
3243 case IPV6_TCLASS:
3244 if (val < -1 || val > 0xff) {
3245 ret = -EINVAL;
3246 } else {
3247 struct ipv6_pinfo *np = inet6_sk(sk);
3248
3249 if (val == -1)
3250 val = 0;
3251 np->tclass = val;
3252 }
3253 break;
3254 default:
3255 ret = -EINVAL;
3256 }
3257#endif
3235 } else if (level == SOL_TCP && 3258 } else if (level == SOL_TCP &&
3236 sk->sk_prot->setsockopt == tcp_setsockopt) { 3259 sk->sk_prot->setsockopt == tcp_setsockopt) {
3237 if (optname == TCP_CONGESTION) { 3260 if (optname == TCP_CONGESTION) {
@@ -3241,7 +3264,8 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
3241 strncpy(name, optval, min_t(long, optlen, 3264 strncpy(name, optval, min_t(long, optlen,
3242 TCP_CA_NAME_MAX-1)); 3265 TCP_CA_NAME_MAX-1));
3243 name[TCP_CA_NAME_MAX-1] = 0; 3266 name[TCP_CA_NAME_MAX-1] = 0;
3244 ret = tcp_set_congestion_control(sk, name, false, reinit); 3267 ret = tcp_set_congestion_control(sk, name, false,
3268 reinit);
3245 } else { 3269 } else {
3246 struct tcp_sock *tp = tcp_sk(sk); 3270 struct tcp_sock *tp = tcp_sk(sk);
3247 3271
@@ -3307,6 +3331,22 @@ BPF_CALL_5(bpf_getsockopt, struct bpf_sock_ops_kern *, bpf_sock,
3307 } else { 3331 } else {
3308 goto err_clear; 3332 goto err_clear;
3309 } 3333 }
3334#if IS_ENABLED(CONFIG_IPV6)
3335 } else if (level == SOL_IPV6) {
3336 struct ipv6_pinfo *np = inet6_sk(sk);
3337
3338 if (optlen != sizeof(int) || sk->sk_family != AF_INET6)
3339 goto err_clear;
3340
3341 /* Only some options are supported */
3342 switch (optname) {
3343 case IPV6_TCLASS:
3344 *((int *)optval) = (int)np->tclass;
3345 break;
3346 default:
3347 goto err_clear;
3348 }
3349#endif
3310 } else { 3350 } else {
3311 goto err_clear; 3351 goto err_clear;
3312 } 3352 }
@@ -3871,6 +3911,7 @@ static bool sock_ops_is_valid_access(int off, int size,
3871 if (type == BPF_WRITE) { 3911 if (type == BPF_WRITE) {
3872 switch (off) { 3912 switch (off) {
3873 case offsetof(struct bpf_sock_ops, reply): 3913 case offsetof(struct bpf_sock_ops, reply):
3914 case offsetof(struct bpf_sock_ops, sk_txhash):
3874 if (size != size_default) 3915 if (size != size_default)
3875 return false; 3916 return false;
3876 break; 3917 break;
@@ -4690,7 +4731,8 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
4690 break; 4731 break;
4691 4732
4692 case offsetof(struct bpf_sock_ops, sk_txhash): 4733 case offsetof(struct bpf_sock_ops, sk_txhash):
4693 SOCK_OPS_GET_FIELD(sk_txhash, sk_txhash, struct sock); 4734 SOCK_OPS_GET_OR_SET_FIELD(sk_txhash, sk_txhash,
4735 struct sock, type);
4694 break; 4736 break;
4695 4737
4696 case offsetof(struct bpf_sock_ops, bytes_received): 4738 case offsetof(struct bpf_sock_ops, bytes_received):
@@ -4701,6 +4743,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
4701 case offsetof(struct bpf_sock_ops, bytes_acked): 4743 case offsetof(struct bpf_sock_ops, bytes_acked):
4702 SOCK_OPS_GET_FIELD(bytes_acked, bytes_acked, struct tcp_sock); 4744 SOCK_OPS_GET_FIELD(bytes_acked, bytes_acked, struct tcp_sock);
4703 break; 4745 break;
4746
4704 } 4747 }
4705 return insn - insn_buf; 4748 return insn - insn_buf;
4706} 4749}