OSDN Git Service

Merge tag 'ceph-for-5.1-rc3' of git://github.com/ceph/ceph-client
[uclinux-h8/linux.git] / tools / testing / selftests / bpf / progs / test_sock_fields_kern.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019 Facebook */
3
4 #include <linux/bpf.h>
5 #include <netinet/in.h>
6 #include <stdbool.h>
7
8 #include "bpf_helpers.h"
9 #include "bpf_endian.h"
10
11 enum bpf_addr_array_idx {
12         ADDR_SRV_IDX,
13         ADDR_CLI_IDX,
14         __NR_BPF_ADDR_ARRAY_IDX,
15 };
16
17 enum bpf_result_array_idx {
18         EGRESS_SRV_IDX,
19         EGRESS_CLI_IDX,
20         INGRESS_LISTEN_IDX,
21         __NR_BPF_RESULT_ARRAY_IDX,
22 };
23
24 enum bpf_linum_array_idx {
25         EGRESS_LINUM_IDX,
26         INGRESS_LINUM_IDX,
27         __NR_BPF_LINUM_ARRAY_IDX,
28 };
29
30 struct bpf_map_def SEC("maps") addr_map = {
31         .type = BPF_MAP_TYPE_ARRAY,
32         .key_size = sizeof(__u32),
33         .value_size = sizeof(struct sockaddr_in6),
34         .max_entries = __NR_BPF_ADDR_ARRAY_IDX,
35 };
36
37 struct bpf_map_def SEC("maps") sock_result_map = {
38         .type = BPF_MAP_TYPE_ARRAY,
39         .key_size = sizeof(__u32),
40         .value_size = sizeof(struct bpf_sock),
41         .max_entries = __NR_BPF_RESULT_ARRAY_IDX,
42 };
43
44 struct bpf_map_def SEC("maps") tcp_sock_result_map = {
45         .type = BPF_MAP_TYPE_ARRAY,
46         .key_size = sizeof(__u32),
47         .value_size = sizeof(struct bpf_tcp_sock),
48         .max_entries = __NR_BPF_RESULT_ARRAY_IDX,
49 };
50
51 struct bpf_map_def SEC("maps") linum_map = {
52         .type = BPF_MAP_TYPE_ARRAY,
53         .key_size = sizeof(__u32),
54         .value_size = sizeof(__u32),
55         .max_entries = __NR_BPF_LINUM_ARRAY_IDX,
56 };
57
58 static bool is_loopback6(__u32 *a6)
59 {
60         return !a6[0] && !a6[1] && !a6[2] && a6[3] == bpf_htonl(1);
61 }
62
63 static void skcpy(struct bpf_sock *dst,
64                   const struct bpf_sock *src)
65 {
66         dst->bound_dev_if = src->bound_dev_if;
67         dst->family = src->family;
68         dst->type = src->type;
69         dst->protocol = src->protocol;
70         dst->mark = src->mark;
71         dst->priority = src->priority;
72         dst->src_ip4 = src->src_ip4;
73         dst->src_ip6[0] = src->src_ip6[0];
74         dst->src_ip6[1] = src->src_ip6[1];
75         dst->src_ip6[2] = src->src_ip6[2];
76         dst->src_ip6[3] = src->src_ip6[3];
77         dst->src_port = src->src_port;
78         dst->dst_ip4 = src->dst_ip4;
79         dst->dst_ip6[0] = src->dst_ip6[0];
80         dst->dst_ip6[1] = src->dst_ip6[1];
81         dst->dst_ip6[2] = src->dst_ip6[2];
82         dst->dst_ip6[3] = src->dst_ip6[3];
83         dst->dst_port = src->dst_port;
84         dst->state = src->state;
85 }
86
87 static void tpcpy(struct bpf_tcp_sock *dst,
88                   const struct bpf_tcp_sock *src)
89 {
90         dst->snd_cwnd = src->snd_cwnd;
91         dst->srtt_us = src->srtt_us;
92         dst->rtt_min = src->rtt_min;
93         dst->snd_ssthresh = src->snd_ssthresh;
94         dst->rcv_nxt = src->rcv_nxt;
95         dst->snd_nxt = src->snd_nxt;
96         dst->snd_una = src->snd_una;
97         dst->mss_cache = src->mss_cache;
98         dst->ecn_flags = src->ecn_flags;
99         dst->rate_delivered = src->rate_delivered;
100         dst->rate_interval_us = src->rate_interval_us;
101         dst->packets_out = src->packets_out;
102         dst->retrans_out = src->retrans_out;
103         dst->total_retrans = src->total_retrans;
104         dst->segs_in = src->segs_in;
105         dst->data_segs_in = src->data_segs_in;
106         dst->segs_out = src->segs_out;
107         dst->data_segs_out = src->data_segs_out;
108         dst->lost_out = src->lost_out;
109         dst->sacked_out = src->sacked_out;
110         dst->bytes_received = src->bytes_received;
111         dst->bytes_acked = src->bytes_acked;
112 }
113
114 #define RETURN {                                                \
115         linum = __LINE__;                                       \
116         bpf_map_update_elem(&linum_map, &linum_idx, &linum, 0); \
117         return 1;                                               \
118 }
119
120 SEC("cgroup_skb/egress")
121 int egress_read_sock_fields(struct __sk_buff *skb)
122 {
123         __u32 srv_idx = ADDR_SRV_IDX, cli_idx = ADDR_CLI_IDX, result_idx;
124         struct sockaddr_in6 *srv_sa6, *cli_sa6;
125         struct bpf_tcp_sock *tp, *tp_ret;
126         struct bpf_sock *sk, *sk_ret;
127         __u32 linum, linum_idx;
128
129         linum_idx = EGRESS_LINUM_IDX;
130
131         sk = skb->sk;
132         if (!sk || sk->state == 10)
133                 RETURN;
134
135         sk = bpf_sk_fullsock(sk);
136         if (!sk || sk->family != AF_INET6 || sk->protocol != IPPROTO_TCP ||
137             !is_loopback6(sk->src_ip6))
138                 RETURN;
139
140         tp = bpf_tcp_sock(sk);
141         if (!tp)
142                 RETURN;
143
144         srv_sa6 = bpf_map_lookup_elem(&addr_map, &srv_idx);
145         cli_sa6 = bpf_map_lookup_elem(&addr_map, &cli_idx);
146         if (!srv_sa6 || !cli_sa6)
147                 RETURN;
148
149         if (sk->src_port == bpf_ntohs(srv_sa6->sin6_port))
150                 result_idx = EGRESS_SRV_IDX;
151         else if (sk->src_port == bpf_ntohs(cli_sa6->sin6_port))
152                 result_idx = EGRESS_CLI_IDX;
153         else
154                 RETURN;
155
156         sk_ret = bpf_map_lookup_elem(&sock_result_map, &result_idx);
157         tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &result_idx);
158         if (!sk_ret || !tp_ret)
159                 RETURN;
160
161         skcpy(sk_ret, sk);
162         tpcpy(tp_ret, tp);
163
164         RETURN;
165 }
166
167 SEC("cgroup_skb/ingress")
168 int ingress_read_sock_fields(struct __sk_buff *skb)
169 {
170         __u32 srv_idx = ADDR_SRV_IDX, result_idx = INGRESS_LISTEN_IDX;
171         struct bpf_tcp_sock *tp, *tp_ret;
172         struct bpf_sock *sk, *sk_ret;
173         struct sockaddr_in6 *srv_sa6;
174         __u32 linum, linum_idx;
175
176         linum_idx = INGRESS_LINUM_IDX;
177
178         sk = skb->sk;
179         if (!sk || sk->family != AF_INET6 || !is_loopback6(sk->src_ip6))
180                 RETURN;
181
182         srv_sa6 = bpf_map_lookup_elem(&addr_map, &srv_idx);
183         if (!srv_sa6 || sk->src_port != bpf_ntohs(srv_sa6->sin6_port))
184                 RETURN;
185
186         if (sk->state != 10 && sk->state != 12)
187                 RETURN;
188
189         sk = bpf_get_listener_sock(sk);
190         if (!sk)
191                 RETURN;
192
193         tp = bpf_tcp_sock(sk);
194         if (!tp)
195                 RETURN;
196
197         sk_ret = bpf_map_lookup_elem(&sock_result_map, &result_idx);
198         tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &result_idx);
199         if (!sk_ret || !tp_ret)
200                 RETURN;
201
202         skcpy(sk_ret, sk);
203         tpcpy(tp_ret, tp);
204
205         RETURN;
206 }
207
208 char _license[] SEC("license") = "GPL";